From 168c7f306fb2c8f2752aff806224299b4a04fc30 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 6 Apr 2020 13:10:16 +0300 Subject: [PATCH] FIR: Fix ambiguity for invoke candidates on qualifier receiver --- .../problems/invokePriority.kt | 2 +- .../problems/invokePriority.txt | 2 +- .../calls/tower/FirTowerResolverSession.kt | 59 +++++++++++++------ .../fir/resolve/calls/tower/TowerGroup.kt | 2 + 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.kt index 74b52ae311b..52582b87302 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.kt @@ -29,6 +29,6 @@ class E { } fun main() { - E.f() // Resolves to (2) in old FE (ambiguity in FIR) + E.f() // Resolves to (2) in old FE (Resolves to (1) in FIR) E.f.invoke() // Resolves to (1) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.txt index f2be2a821d0..e21660fc6e6 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/invokePriority.txt @@ -74,6 +74,6 @@ FILE: invokePriority.kt } public final fun main(): R|kotlin/Unit| { - Q|E|.#() + Q|E.f|.R|/E.f.invoke|() Q|E.f|.R|/E.f.invoke|() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt index 847b3d66154..fc996f612f8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/FirTowerResolverSession.kt @@ -87,7 +87,10 @@ class FirTowerResolverSession internal constructor( group: TowerGroup, explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, invokeResolveMode: InvokeResolveMode? = null, - candidateFactory: CandidateFactory = candidateFactoriesAndCollectors.candidateFactory + candidateFactory: CandidateFactory = candidateFactoriesAndCollectors.candidateFactory, + // Non-trivial only for qualifier receiver, because there we should prioritize invokes that were found + // at Qualifier scopes above candidates found in QualifierAsExpression receiver + useParentGroupForInvokes: Boolean = false ): ProcessorAction { manager.requestGroup(group) @@ -98,7 +101,8 @@ class FirTowerResolverSession internal constructor( candidateFactoriesAndCollectors, towerLevel, invokeResolveMode, candidateFactory ) { enqueueResolverTasksForInvokeReceiverCandidates( - invokeResolveMode, callInfo + invokeResolveMode, callInfo, + parentGroupForInvokeCandidates = if (useParentGroupForInvokes) group else TowerGroup.EmptyRoot ) } } @@ -139,7 +143,8 @@ class FirTowerResolverSession internal constructor( for ((depth, qualifierScope) in qualifierReceiver.callableScopes().withIndex()) { processLevel( qualifierScope.toScopeTowerLevel(noInnerConstructors = true), - info.noStubReceiver(), TowerGroup.Qualifier(depth) + info.noStubReceiver(), TowerGroup.Qualifier(depth), + useParentGroupForInvokes = true, ) } } @@ -153,9 +158,11 @@ class FirTowerResolverSession internal constructor( qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol ) return val scope = qualifierReceiver.classifierScope() ?: return + val group = if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier processLevel( scope.toScopeTowerLevel(noInnerConstructors = true), info.noStubReceiver(), - if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier + group, + useParentGroupForInvokes = true, ) } @@ -482,11 +489,12 @@ class FirTowerResolverSession internal constructor( private suspend fun runResolverForInvoke( info: CallInfo, invokeReceiverValue: ExpressionReceiverValue, - invokeOnGivenReceiverCandidateFactory: CandidateFactory + invokeOnGivenReceiverCandidateFactory: CandidateFactory, + parentGroupForInvokeCandidates: TowerGroup ) { processLevelForRegularInvoke( invokeReceiverValue.toMemberScopeTowerLevel(), - info, TowerGroup.Member, + info, parentGroupForInvokeCandidates.Member, ExplicitReceiverKind.DISPATCH_RECEIVER, invokeOnGivenReceiverCandidateFactory ) @@ -494,7 +502,7 @@ class FirTowerResolverSession internal constructor( for ((index, localScope) in localScopes.withIndex()) { processLevelForRegularInvoke( localScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, TowerGroup.Local(index), + info, parentGroupForInvokeCandidates.Local(index), ExplicitReceiverKind.EXTENSION_RECEIVER, invokeOnGivenReceiverCandidateFactory ) @@ -502,10 +510,10 @@ class FirTowerResolverSession internal constructor( for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { // NB: companions are processed via implicitReceiverValues! - val parentGroup = TowerGroup.Implicit(depth) + val group = parentGroupForInvokeCandidates.Implicit(depth).Member processLevelForRegularInvoke( implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, parentGroup.Member, + info, group, ExplicitReceiverKind.EXTENSION_RECEIVER, invokeOnGivenReceiverCandidateFactory ) @@ -514,7 +522,7 @@ class FirTowerResolverSession internal constructor( for ((index, topLevelScope) in topLevelScopes.withIndex()) { processLevelForRegularInvoke( topLevelScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, TowerGroup.Top(index), + info, parentGroupForInvokeCandidates.Top(index), ExplicitReceiverKind.EXTENSION_RECEIVER, invokeOnGivenReceiverCandidateFactory ) @@ -537,11 +545,12 @@ class FirTowerResolverSession internal constructor( private suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument( info: CallInfo, invokeReceiverValue: ExpressionReceiverValue, - invokeOnGivenReceiverCandidateFactory: CandidateFactory + invokeOnGivenReceiverCandidateFactory: CandidateFactory, + parentGroupForInvokeCandidates: TowerGroup ) { processLevel( invokeReceiverValue.toMemberScopeTowerLevel(), - info, TowerGroup.Member.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION), + info, parentGroupForInvokeCandidates.Member.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION), ExplicitReceiverKind.DISPATCH_RECEIVER, InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER, invokeOnGivenReceiverCandidateFactory @@ -552,10 +561,16 @@ class FirTowerResolverSession internal constructor( private suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument( info: CallInfo, invokeReceiverValue: ExpressionReceiverValue, - invokeOnGivenReceiverCandidateFactory: CandidateFactory + invokeOnGivenReceiverCandidateFactory: CandidateFactory, + parentGroupForInvokeCandidates: TowerGroup ) { for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - val towerGroup = TowerGroup.Implicit(depth).InvokeExtension.InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION) + val towerGroup = + parentGroupForInvokeCandidates + .Implicit(depth) + .InvokeExtension + .InvokeResolvePriority(InvokeResolvePriority.INVOKE_EXTENSION) + processLevel( invokeReceiverValue.toMemberScopeTowerLevel( extensionReceiver = implicitReceiverValue, @@ -572,6 +587,7 @@ class FirTowerResolverSession internal constructor( private fun enqueueResolverTasksForInvokeReceiverCandidates( invokeResolveMode: InvokeResolveMode?, info: CallInfo, + parentGroupForInvokeCandidates: TowerGroup ) { val invokeBuiltinExtensionMode = invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION @@ -612,7 +628,8 @@ class FirTowerResolverSession internal constructor( invokeFunctionInfo, explicitReceiver, invokeBuiltinExtensionMode, - useImplicitReceiverAsBuiltinInvokeArgument + useImplicitReceiverAsBuiltinInvokeArgument, + parentGroupForInvokeCandidates ) } } @@ -621,13 +638,15 @@ class FirTowerResolverSession internal constructor( invokeFunctionInfo: CallInfo, explicitReceiver: ExpressionReceiverValue, invokeBuiltinExtensionMode: Boolean, - useImplicitReceiverAsBuiltinInvokeArgument: Boolean + useImplicitReceiverAsBuiltinInvokeArgument: Boolean, + parentGroupForInvokeCandidates: TowerGroup ) { val invokeOnGivenReceiverCandidateFactory = CandidateFactory(components, invokeFunctionInfo) if (invokeBuiltinExtensionMode) { manager.enqueueResolverTask { runResolverForBuiltinInvokeExtensionWithExplicitArgument( - invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory + invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory, + parentGroupForInvokeCandidates ) } @@ -637,14 +656,16 @@ class FirTowerResolverSession internal constructor( if (useImplicitReceiverAsBuiltinInvokeArgument) { manager.enqueueResolverTask { runResolverForBuiltinInvokeExtensionWithImplicitArgument( - invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory + invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory, + parentGroupForInvokeCandidates ) } } manager.enqueueResolverTask { runResolverForInvoke( - invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory + invokeFunctionInfo, explicitReceiver, invokeOnGivenReceiverCandidateFactory, + parentGroupForInvokeCandidates ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt index 1195e7a9693..58e84c4addb 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerGroup.kt @@ -51,6 +51,8 @@ private constructor( companion object { private fun kindOf(kind: TowerGroupKind): TowerGroup = TowerGroup(arrayOf(kind)) + val EmptyRoot = TowerGroup(emptyArray()) + val Start = kindOf(TowerGroupKind.Start) val ClassifierPrioritized = kindOf(TowerGroupKind.ClassifierPrioritized)