diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt index 938711e4e9d..d38cb737547 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt @@ -96,6 +96,7 @@ internal class InvokeTowerProcessor( // todo filter by operator override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor { val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false) + ?: return KnownResultProcessor(emptyList()) return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions) } } @@ -110,6 +111,7 @@ internal class InvokeExtensionTowerProcessor( override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor { val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true) + ?: return KnownResultProcessor(emptyList()) val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver) ?: return KnownResultProcessor(emptyList()) return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index 623ffafe005..a31143776ae 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden import org.jetbrains.kotlin.resolve.scopes.receivers.* +import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.util.OperatorNameConventions @@ -243,7 +244,7 @@ class NewResolveOldInference( return Context(scopeTower, name, basicCallResolutionContext, tracing) } - override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair> { + override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair>? { assert(variable.resolvedCall.status.possibleTransformToSuccess()) { "Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " + "and descriptor: ${variable.resolvedCall.candidateDescriptor}" @@ -253,8 +254,13 @@ class NewResolveOldInference( assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null && variableDescriptor is VariableDescriptor) { "Unexpected varialbe candidate: $variable" } + val variableType = (variableDescriptor as VariableDescriptor).type + + if (variableType is DeferredType && variableType.isComputing) { + return null // todo: create special check that there is no invoke on variable + } val variableReceiver = ExpressionReceiver.create(calleeExpression!!, - (variableDescriptor as VariableDescriptor).type, + variableType, basicCallContext.trace.bindingContext) // used for smartCasts, see: DataFlowValueFactory.getIdForSimpleNameExpression tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index 90525040ff5..0befbd781a4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -39,7 +39,8 @@ interface TowerContext { fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext // foo() -> ReceiverValue(foo), context for invoke - fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair> + // null means that there is no invoke on variable + fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair>? } internal sealed class TowerData { diff --git a/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.kt b/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.kt new file mode 100644 index 00000000000..f97d9568425 --- /dev/null +++ b/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.kt @@ -0,0 +1,16 @@ +fun test() = 3 + +fun proxy(t: T) = t + +class A { + val test = test() +} + +class B { + val test = proxy(test()) +} + +class C { + val bar = test() + val test = bar() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.txt b/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.txt new file mode 100644 index 00000000000..cadd24ca7df --- /dev/null +++ b/compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.txt @@ -0,0 +1,29 @@ +package + +public fun proxy(/*0*/ t: T): T +public fun test(): kotlin.Int + +public final class A { + public constructor A() + public final val test: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B() + public final val test: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C { + public constructor C() + public final val bar: [ERROR : ] + public final val test: [ERROR : Type for bar()] + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index de7564b5cfe..6373915ca7c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -325,6 +325,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("InvokeAndRecursiveResolve.kt") + public void testInvokeAndRecursiveResolve() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/InvokeAndRecursiveResolve.kt"); + doTest(fileName); + } + @TestMetadata("IsExpressions.kt") public void testIsExpressions() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/IsExpressions.kt");