diff --git a/compiler/fir/analysis-tests/testData/resolve/kt41990.kt b/compiler/fir/analysis-tests/testData/resolve/kt41990.kt new file mode 100644 index 00000000000..636d7d35f6e --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/kt41990.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-41990 + +fun getLambda(): String.() -> Unit = null!! + +fun String.test_1(s: String) { + getLambda()() + getLambda()(s) +} diff --git a/compiler/fir/analysis-tests/testData/resolve/kt41990.txt b/compiler/fir/analysis-tests/testData/resolve/kt41990.txt new file mode 100644 index 00000000000..dd7c870819b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/kt41990.txt @@ -0,0 +1,8 @@ +FILE: kt41990.kt + public final fun getLambda(): R|kotlin/String.() -> kotlin/Unit| { + ^getLambda Null(null)!! + } + public final fun R|kotlin/String|.test_1(s: R|kotlin/String|): R|kotlin/Unit| { + R|/getLambda|().R|FakeOverride|(this@R|/test_1|) + R|/getLambda|().R|FakeOverride|(R|/s|) + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 511edbd7111..066c8d2c226 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -243,6 +243,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt"); } + @TestMetadata("kt41990.kt") + public void testKt41990() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt"); + } + @TestMetadata("labelAndReceiverForInfix.kt") public void testLabelAndReceiverForInfix() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 6f728513da8..692dfe029e9 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -243,6 +243,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/javaStaticScopeInheritance.kt"); } + @TestMetadata("kt41990.kt") + public void testKt41990() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt"); + } + @TestMetadata("labelAndReceiverForInfix.kt") public void testLabelAndReceiverForInfix() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 72f0bf16e35..93faf9a0ae3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -141,6 +141,7 @@ class FirCallResolver( isPotentialQualifierPart = qualifiedAccess !is FirFunctionCall && qualifiedAccess.explicitReceiver is FirResolvedQualifier && qualifiedResolver.isPotentialQualifierPartPosition(), + isImplicitInvoke = qualifiedAccess is FirImplicitInvokeCall, typeArguments, session, components.file, @@ -300,6 +301,7 @@ class FirCallResolver( explicitReceiver = null, delegatedConstructorCall.argumentList, isPotentialQualifierPart = false, + isImplicitInvoke = false, typeArguments = typeArguments, session, components.file, @@ -347,6 +349,7 @@ class FirCallResolver( explicitReceiver = null, annotationCall.argumentList, isPotentialQualifierPart = false, + isImplicitInvoke = false, typeArguments = emptyList(), session, components.file, @@ -449,6 +452,7 @@ class FirCallResolver( callableReferenceAccess.explicitReceiver, FirEmptyArgumentList, isPotentialQualifierPart = false, + isImplicitInvoke = false, emptyList(), session, components.file, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index 02e5f8b0b36..7042a081837 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -38,6 +38,7 @@ data class CallInfo( val explicitReceiver: FirExpression?, val argumentList: FirArgumentList, val isPotentialQualifierPart: Boolean, + val isImplicitInvoke: Boolean, val typeArguments: List, val session: FirSession, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirInvokeResolveTowerExtension.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirInvokeResolveTowerExtension.kt index e264c6b916b..6c4e401f8e6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirInvokeResolveTowerExtension.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirInvokeResolveTowerExtension.kt @@ -184,15 +184,7 @@ internal class FirInvokeResolveTowerExtension( receiverGroup: TowerGroup ) { val invokeOnGivenReceiverCandidateFactory = CandidateFactory(context, invokeFunctionInfo) - val task = InvokeFunctionResolveTask( - components, - manager, - TowerDataElementsForName(invokeFunctionInfo.name, components.towerDataContext), - receiverGroup, - candidateFactoriesAndCollectors.resultCollector, - invokeOnGivenReceiverCandidateFactory, - candidateFactoriesAndCollectors.stubReceiverCandidateFactory - ) + val task = createInvokeFunctionResolveTask(invokeFunctionInfo, receiverGroup, invokeOnGivenReceiverCandidateFactory) if (invokeBuiltinExtensionMode) { manager.enqueueResolverTask { task.runResolverForBuiltinInvokeExtensionWithExplicitArgument( @@ -219,6 +211,42 @@ internal class FirInvokeResolveTowerExtension( } } + fun enqueueResolveTasksForImplicitInvokeCall(info: CallInfo, receiverExpression: FirExpression) { + val explicitReceiverValue = ExpressionReceiverValue(receiverExpression) + val task = createInvokeFunctionResolveTask(info, TowerGroup.EmptyRoot) + manager.enqueueResolverTask { + task.runResolverForInvoke( + info, explicitReceiverValue, + TowerGroup.EmptyRoot + ) + } + manager.enqueueResolverTask { + task.runResolverForBuiltinInvokeExtensionWithExplicitArgument( + info, explicitReceiverValue, + TowerGroup.EmptyRoot + ) + } + manager.enqueueResolverTask { + task.runResolverForBuiltinInvokeExtensionWithImplicitArgument( + info, explicitReceiverValue, + TowerGroup.EmptyRoot + ) + } + } + + private fun createInvokeFunctionResolveTask( + info: CallInfo, + receiverGroup: TowerGroup, + candidateFactory: CandidateFactory = candidateFactoriesAndCollectors.candidateFactory + ): InvokeFunctionResolveTask = InvokeFunctionResolveTask( + components, + manager, + TowerDataElementsForName(info.name, components.towerDataContext), + receiverGroup, + candidateFactoriesAndCollectors.resultCollector, + candidateFactory, + candidateFactoriesAndCollectors.stubReceiverCandidateFactory + ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt index 4b63129157c..b554f085d0a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolver.kt @@ -66,10 +66,14 @@ class FirTowerResolver( if (receiver is FirQualifiedAccessExpression) { val calleeReference = receiver.calleeReference if (calleeReference is FirSuperReference) { - return manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) } + manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) } + return } } - + if (info.isImplicitInvoke) { + invokeResolveTowerExtension.enqueueResolveTasksForImplicitInvokeCall(info, receiver) + return + } manager.enqueueResolverTask { mainTask.runResolverForExpressionReceiver(info, receiver) } invokeResolveTowerExtension.enqueueResolveTasksForExpressionReceiver(info, receiver) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index 1d17a4c42db..e3862164d1b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -184,6 +184,7 @@ class FirSyntheticCallGenerator( explicitReceiver = null, argumentList = argumentList, isPotentialQualifierPart = false, + isImplicitInvoke = false, typeArguments = emptyList(), session = session, containingFile = components.file, diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt index 3639d81d5f5..8b51b8f9b4b 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.fir.kt @@ -15,7 +15,7 @@ fun test(a: A) { (a.x)() if (a.x != null) { a.x() // todo - (a.x)() + (a.x)() } } } diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt index a7c8c04aa1e..2ba657f428d 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt @@ -27,7 +27,7 @@ fun test(a: A, b: B) { a.foo() a.(foo)() - (a.foo)() + (a.foo)() (a.foo)(this) a.foo(this) @@ -69,7 +69,7 @@ fun test(a: A, b: B) { a.foo() a.(foo)() - (a.foo)() + (a.foo)() (a.foo)(this) a.foo(this) diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/kt9805.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/kt9805.fir.kt index a0e0b9c1208..e4ebeaadaae 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/kt9805.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/kt9805.fir.kt @@ -10,7 +10,7 @@ fun test(a: A, b: B) { a.foo(this) - (a.foo)() + (a.foo)() (a.foo)(this) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/resolver/candidateInfoProviders.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/resolver/candidateInfoProviders.kt index 44767ae3ba7..8f2ce95f48b 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/resolver/candidateInfoProviders.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/resolver/candidateInfoProviders.kt @@ -44,6 +44,7 @@ abstract class AbstractCandidateInfoProvider( containingDeclarations = emptyList(), // TODO - maybe we should pass declarations from context here (no visible differences atm) containingFile = firFile, isPotentialQualifierPart = false, + isImplicitInvoke = false, session = firSession, ) } @@ -85,4 +86,4 @@ class CheckExtensionForCompletionCandidateInfoProvider( val candidateHasExtensionReceiver = callableSymbol.fir.receiverTypeRef != null callHasExtensionReceiver != candidateHasExtensionReceiver } -} \ No newline at end of file +}