From b7dd63465bd4a2637102e9e5c9fef92880ef1e80 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 27 Nov 2014 09:37:40 +0300 Subject: [PATCH] Allow invoke-convention on dynamic expressions --- .../lang/resolve/calls/tasks/TaskPrioritizer.java | 3 +-- .../jet/lang/resolve/calls/tasks/dynamicCalls.kt | 6 ++++++ .../diagnostics/tests/dynamicTypes/conventions.kt | 15 +++++++++++---- spec-docs/dynamic-types.md | 2 ++ 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index b266191f48e..733812c97cd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -124,8 +124,7 @@ public class TaskPrioritizer { ) { ProgressIndicatorProvider.checkCanceled(); - ReceiverValue dispatchReceiver = c.context.call.getDispatchReceiver(); - boolean resolveInvoke = dispatchReceiver.exists() && !TypesPackage.isDynamic(dispatchReceiver.getType()); + boolean resolveInvoke = c.context.call.getDispatchReceiver().exists(); if (resolveInvoke) { addCandidatesForInvoke(receiver, c); return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt index eafef2bcfeb..1bbcfdaa75d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt @@ -61,6 +61,12 @@ object DynamicCallableDescriptors { override fun getFunctions(name: Name): Collection { if (isAugmentedAssignmentConvention(name)) return listOf() + if (call.getCallType() == Call.CallType.INVOKE + && call.getValueArgumentList() == null && call.getFunctionLiteralArguments().isEmpty()) { + // this means that we are looking for "imaginary" invokes, + // e.g. in `+d` we are looking for property "plus" with member "invoke" + return listOf() + } return listOf(createDynamicFunction(owner, name, call)) } diff --git a/compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt b/compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt index 00efbce417b..584c2cce131 100644 --- a/compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt +++ b/compiler/testData/diagnostics/tests/dynamicTypes/conventions.kt @@ -40,10 +40,17 @@ fun test(d: dynamic) { d[1]-- --d[1] -// d() -// d(1) -// d(name = 1) -// d {} + d() + d(1) + d(name = 1) + d {} + + class C { + val plus: dynamic = null + } + + C() + 5 + C().plus(5) d == d d != d diff --git a/spec-docs/dynamic-types.md b/spec-docs/dynamic-types.md index 04b4575f1e3..3e46760fc2f 100644 --- a/spec-docs/dynamic-types.md +++ b/spec-docs/dynamic-types.md @@ -72,6 +72,8 @@ Internally, `dynamic` is represented as a flexible type `Nothing..Any?`, with th If needed, one can force a call to an extension by casting the receiver to a static type: `(d as Foo).bar()` - Augmented assignments on dynamic receivers (e.g. `dyn += foo`) are resolved to `plusAssign()` function, not `plus`, for generality: this permits calling them on vals (e.g. those holding collection-like objects) +- The invoke convention is limited so that for calls like `dyn.foo()` we do not look for property `foo` that has `invoke` defined on it + (same for other cases like `+dyn` etc) ## Type Argument Inference