diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolver.kt index 91cbc8df558..d641cb15f21 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolver.kt @@ -5,538 +5,16 @@ package org.jetbrains.kotlin.fir.resolve.calls -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.isCompanion -import org.jetbrains.kotlin.fir.declarations.isInner -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier -import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator -import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.ProcessorAction -import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope -import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope -import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef -import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind -import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST class FirTowerResolver( val typeCalculator: ReturnTypeCalculator, val components: BodyResolveComponents, resolutionStageRunner: ResolutionStageRunner, ) { - private val localScopes: List get() = components.localScopes.asReversed() - private val topLevelScopes: List - get() { - if (components.typeParametersScopes.isEmpty()) return components.fileImportsScope.asReversed() - return components.typeParametersScopes.asReversed() + components.fileImportsScope.asReversed() - } - - private val session: FirSession get() = components.session private val collector = CandidateCollector(components, resolutionStageRunner) private val manager = TowerResolveManager() - private lateinit var implicitReceivers: List - private lateinit var implicitReceiversUsableAsValues: List - - private data class ImplicitReceiver( - val receiver: ImplicitReceiverValue<*>, - val depth: Int, - val usableAsValue: Boolean - ) - - private fun prepareImplicitReceivers(implicitReceiverValues: List>) { - var depth = 0 - var firstDispatchValue = true - val explicitCompanions = mutableListOf() - val implicitReceiversUsableAsValues = mutableListOf() - implicitReceivers = implicitReceiverValues.mapNotNull { receiverValue -> - val usableAsValue = when (receiverValue) { - is ImplicitExtensionReceiverValue -> true - is ImplicitDispatchReceiverValue -> { - val symbol = receiverValue.boundSymbol - val klass = symbol.fir as? FirRegularClass - - if (!receiverValue.implicitCompanion && klass?.isCompanion == true) { - explicitCompanions += klass.symbol - } - - if (firstDispatchValue && !receiverValue.inDelegated) { - if (!receiverValue.implicitCompanion && - klass?.isInner == false && - !symbol.classId.isLocal - ) { - firstDispatchValue = false - } - true - } else { - symbol.fir.classKind == ClassKind.OBJECT && !receiverValue.inDelegated - } - } - } - - if (receiverValue is ImplicitDispatchReceiverValue && receiverValue.implicitCompanion && receiverValue.boundSymbol in explicitCompanions) { - null - } else { - ImplicitReceiver(receiverValue, depth++, usableAsValue).also { - if (usableAsValue) { - implicitReceiversUsableAsValues.add(it) - } - } - } - } - - this.implicitReceiversUsableAsValues = implicitReceiversUsableAsValues - } - - private fun FirScope.toScopeTowerLevel( - extensionReceiver: ReceiverValue? = null, - extensionsOnly: Boolean = false, - noInnerConstructors: Boolean = false - ): ScopeTowerLevel = ScopeTowerLevel( - session, components, this, - extensionReceiver, extensionsOnly, noInnerConstructors - ) - - private fun ReceiverValue.toMemberScopeTowerLevel( - extensionReceiver: ReceiverValue? = null, - implicitExtensionInvokeMode: Boolean = false - ) = MemberScopeTowerLevel( - session, components, this, - extensionReceiver, implicitExtensionInvokeMode, - scopeSession = components.scopeSession - ) - - private suspend fun processQualifierScopes( - manager: TowerResolveManager, - info: CallInfo, qualifierReceiver: QualifierReceiver? - ) { - if (qualifierReceiver == null) return - for ((depth, qualifierScope) in qualifierReceiver.callableScopes().withIndex()) { - manager.processLevel( - qualifierScope.toScopeTowerLevel(noInnerConstructors = true), - info.noStubReceiver(), TowerGroup.Qualifier(depth) - ) - } - } - - private suspend fun processClassifierScope( - manager: TowerResolveManager, - info: CallInfo, qualifierReceiver: QualifierReceiver?, prioritized: Boolean - ) { - if (qualifierReceiver == null) return - if (info.callKind != CallKind.CallableReference && - qualifierReceiver is ClassQualifierReceiver && - qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol - ) return - val scope = qualifierReceiver.classifierScope() ?: return - manager.processLevel( - scope.toScopeTowerLevel(noInnerConstructors = true), info.noStubReceiver(), - if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier - ) - } - - private suspend fun runResolverForQualifierReceiver( - info: CallInfo, - resolvedQualifier: FirResolvedQualifier, - manager: TowerResolveManager - ) { - val qualifierReceiver = createQualifierReceiver(resolvedQualifier, session, components.scopeSession) - - when { - info.isPotentialQualifierPart -> { - processClassifierScope(manager, info, qualifierReceiver, prioritized = true) - processQualifierScopes(manager, info, qualifierReceiver) - } - else -> { - processQualifierScopes(manager, info, qualifierReceiver) - processClassifierScope(manager, info, qualifierReceiver, prioritized = false) - } - } - - if (resolvedQualifier.symbol != null) { - val typeRef = resolvedQualifier.typeRef - // NB: yet built-in Unit is used for "no-value" type - if (info.callKind == CallKind.CallableReference) { - if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) { - runResolverForExpressionReceiver(info, resolvedQualifier, manager) - } - } else { - if (typeRef !is FirImplicitBuiltinTypeRef) { - runResolverForExpressionReceiver(info, resolvedQualifier, manager) - } - } - } - - } - - private suspend fun runResolverForNoReceiver( - info: CallInfo, - manager: TowerResolveManager - ) { - manager.processExtensionsThatHideMembers(info, explicitReceiverValue = null) - val nonEmptyLocalScopes = mutableListOf() - manager.processLocalScopesWithNoReceiver(info, nonEmptyLocalScopes) - - val emptyTopLevelScopes = mutableSetOf() - manager.processImplicitReceiversWithNoExplicit(info, nonEmptyLocalScopes, emptyTopLevelScopes) - - manager.processTopLevelScopesNoReceiver(info, emptyTopLevelScopes) - } - - private suspend fun TowerResolveManager.processExtensionsThatHideMembers( - info: CallInfo, - explicitReceiverValue: ReceiverValue? - ) { - val shouldProcessExtensionsBeforeMembers = - info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST - - if (!shouldProcessExtensionsBeforeMembers) return - - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - if (explicitReceiverValue != null) { - processHideMembersLevel(explicitReceiverValue, topLevelScope, info, index, depth = null) - } else { - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - processHideMembersLevel(implicitReceiverValue, topLevelScope, info, index, depth) - } - } - } - } - - private suspend fun TowerResolveManager.processHideMembersLevel( - receiverValue: ReceiverValue, - topLevelScope: FirScope, - info: CallInfo, - index: Int, - depth: Int? - ) = processLevel( - topLevelScope.toScopeTowerLevel( - extensionReceiver = receiverValue, extensionsOnly = true - ), - info, TowerGroup.TopPrioritized(index).let { if (depth != null) it.Implicit(depth) else it } - ) - - private suspend fun TowerResolveManager.processLocalScopesWithNoReceiver( - info: CallInfo, - nonEmptyLocalScopes: MutableList - ) { - for ((index, localScope) in localScopes.withIndex()) { - val result = processLevel( - localScope.toScopeTowerLevel(), info, TowerGroup.Local(index) - ) - if (result != ProcessorAction.NONE) { - nonEmptyLocalScopes += localScope - } - } - } - - private suspend fun TowerResolveManager.processImplicitReceiversWithNoExplicit( - info: CallInfo, - nonEmptyLocalScopes: MutableList, - emptyTopLevelScopes: MutableSet - ) { - val implicitReceiverValuesWithEmptyScopes = mutableSetOf>() - for ((implicitReceiverValue, depth, usableAsValue) in implicitReceivers) { - // NB: companions are processed via implicitReceiverValues! - val parentGroup = TowerGroup.Implicit(depth) - - if (usableAsValue) { - processCandidatesWithGivenImplicitReceiverAsValue( - implicitReceiverValue, - this, - info, - parentGroup, - implicitReceiverValuesWithEmptyScopes, - nonEmptyLocalScopes, - emptyTopLevelScopes - ) - } - - if (implicitReceiverValue is ImplicitDispatchReceiverValue) { - val scope = implicitReceiverValue.scope(session, components.scopeSession) - if (scope != null) { - processLevel( - FirStaticScope(scope).toScopeTowerLevel(), - info, parentGroup.Static(depth) - ) - } - } - } - } - - private suspend fun processCandidatesWithGivenImplicitReceiverAsValue( - receiver: ImplicitReceiverValue<*>, - manager: TowerResolveManager, - info: CallInfo, - parentGroup: TowerGroup, - implicitReceiverValuesWithEmptyScopes: MutableSet>, - nonEmptyLocalScopes: List, - emptyTopLevelScopes: MutableSet - ) { - val implicitResult = manager.processLevel( - receiver.toMemberScopeTowerLevel(), info, parentGroup.Member - ) - - if (implicitResult == ProcessorAction.NONE) { - implicitReceiverValuesWithEmptyScopes += receiver - } - - for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { - manager.processLevel( - localScope.toScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Local(localIndex) - ) - } - - for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { - if (implicitDispatchReceiverValue in implicitReceiverValuesWithEmptyScopes) continue - manager.processLevel( - implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Implicit(dispatchDepth) - ) - } - - for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { - if (topLevelScope in emptyTopLevelScopes) continue - val result = manager.processLevel( - topLevelScope.toScopeTowerLevel(extensionReceiver = receiver), - info, parentGroup.Top(topIndex) - ) - if (result == ProcessorAction.NONE) { - emptyTopLevelScopes += topLevelScope - } - } - } - - private suspend fun TowerResolveManager.processTopLevelScopesNoReceiver( - info: CallInfo, - emptyTopLevelScopes: Collection - ) { - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - // NB: this check does not work for variables - // because we do not search for objects if we have extension receiver - if (info.callKind != CallKind.VariableAccess && topLevelScope in emptyTopLevelScopes) continue - processLevel( - topLevelScope.toScopeTowerLevel(), info, TowerGroup.Top(index) - ) - } - } - - private suspend fun runResolverForExpressionReceiver( - info: CallInfo, - receiver: FirExpression, - manager: TowerResolveManager - ) { - val explicitReceiverValue = ExpressionReceiverValue(receiver) - - manager.processExtensionsThatHideMembers(info, explicitReceiverValue) - manager.processMembersForExplicitReceiver(explicitReceiverValue, info) - - val shouldProcessExplicitReceiverScopeOnly = - info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe() != null - if (shouldProcessExplicitReceiverScopeOnly) { - // Special case (integer literal type) - return - } - - val nonEmptyLocalScopes = mutableListOf() - for ((index, localScope) in localScopes.withIndex()) { - if (manager.processScopeForExplicitReceiver( - localScope, - explicitReceiverValue, - info, - TowerGroup.Local(index) - ) != ProcessorAction.NONE - ) { - nonEmptyLocalScopes += localScope - } - } - - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - processCombinationOfReceivers(manager, implicitReceiverValue, explicitReceiverValue, info, depth, nonEmptyLocalScopes) - } - - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - manager.processScopeForExplicitReceiver( - topLevelScope, - explicitReceiverValue, - info, - TowerGroup.Top(index) - ) - } - } - - private suspend fun TowerResolveManager.processScopeForExplicitReceiver( - scope: FirScope, - explicitReceiverValue: ExpressionReceiverValue, - info: CallInfo, - towerGroup: TowerGroup, - ): ProcessorAction { - val result = processLevel( - scope.toScopeTowerLevel(extensionReceiver = explicitReceiverValue), - info, towerGroup, ExplicitReceiverKind.EXTENSION_RECEIVER - ) - - processLevelForPropertyWithInvoke( - scope.toScopeTowerLevel(), info, towerGroup - ) - - return result - } - - private suspend fun TowerResolveManager.processMembersForExplicitReceiver( - explicitReceiverValue: ExpressionReceiverValue, - info: CallInfo - ) { - processLevel( - explicitReceiverValue.toMemberScopeTowerLevel(), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER - ) - } - - private suspend fun processCombinationOfReceivers( - manager: TowerResolveManager, - implicitReceiverValue: ImplicitReceiverValue<*>, - explicitReceiverValue: ExpressionReceiverValue, - info: CallInfo, - depth: Int, - nonEmptyLocalScopes: MutableList - ) { - // NB: companions are processed via implicitReceiverValues! - val parentGroup = TowerGroup.Implicit(depth) - - // Member extensions - manager.processLevel( - implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue), - info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER - ) - // properties for invoke on implicit receiver - manager.processLevelForPropertyWithInvoke( - implicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member - ) - - for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { - manager.processLevelForPropertyWithInvoke( - localScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Local(localIndex) - ) - } - - for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { - manager.processLevelForPropertyWithInvoke( - implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Implicit(dispatchDepth) - ) - } - - for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { - manager.processLevelForPropertyWithInvoke( - topLevelScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), - info, parentGroup.Top(topIndex) - ) - } - } - - private suspend fun runResolverForSuperReceiver( - info: CallInfo, - superTypeRef: FirTypeRef, - manager: TowerResolveManager - ) { - val scope = when (superTypeRef) { - is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession) - is FirComposedSuperTypeRef -> FirCompositeScope( - superTypeRef.superTypeRefs.mapNotNullTo(mutableListOf()) { it.type.scope(session, components.scopeSession) } - ) - else -> null - } ?: return - manager.processLevel( - scope.toScopeTowerLevel(), - info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER - ) - } - - internal suspend fun runResolverForInvoke( - info: CallInfo, - invokeReceiverValue: ExpressionReceiverValue, - manager: TowerResolveManager - ) { - manager.processLevel( - invokeReceiverValue.toMemberScopeTowerLevel(), - info, TowerGroup.Member, - ExplicitReceiverKind.DISPATCH_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - - for ((index, localScope) in localScopes.withIndex()) { - manager.processLevel( - localScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, TowerGroup.Local(index), - ExplicitReceiverKind.EXTENSION_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - } - - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - // NB: companions are processed via implicitReceiverValues! - val parentGroup = TowerGroup.Implicit(depth) - manager.processLevel( - implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, parentGroup.Member, - ExplicitReceiverKind.EXTENSION_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - } - - for ((index, topLevelScope) in topLevelScopes.withIndex()) { - manager.processLevel( - topLevelScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), - info, TowerGroup.Top(index), - ExplicitReceiverKind.EXTENSION_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - } - } - - // Here we already know extension receiver for invoke, and it's stated in info as first argument - internal suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument( - info: CallInfo, - invokeReceiverValue: ExpressionReceiverValue, - manager: TowerResolveManager - ) { - manager.processLevel( - invokeReceiverValue.toMemberScopeTowerLevel(), - info, TowerGroup.Member, - ExplicitReceiverKind.DISPATCH_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - } - - // Here we don't know extension receiver for invoke, assuming it's one of implicit receivers - internal suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument( - info: CallInfo, - invokeReceiverValue: ExpressionReceiverValue, - manager: TowerResolveManager - ) { - for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { - val parentGroup = TowerGroup.Implicit(depth) - manager.processLevel( - invokeReceiverValue.toMemberScopeTowerLevel( - extensionReceiver = implicitReceiverValue, - implicitExtensionInvokeMode = true - ), - info, parentGroup.InvokeExtension, - ExplicitReceiverKind.DISPATCH_RECEIVER, - InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER - ) - } - } fun runResolver( implicitReceiverValues: List>, @@ -544,30 +22,19 @@ class FirTowerResolver( collector: CandidateCollector = this.collector, manager: TowerResolveManager = this.manager ): CandidateCollector { - // TODO: add flag receiver / non-receiver position - prepareImplicitReceivers(implicitReceiverValues) - manager.callResolutionContext = buildCallResolutionContext(info, collector) + val towerResolverSession = FirTowerResolverSession(components, implicitReceiverValues) + manager.callResolutionContext = buildCallResolutionContext(info, collector, towerResolverSession) + + towerResolverSession.runResolve(manager, info) - when (val receiver = info.explicitReceiver) { - is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) } - null -> manager.enqueueResolverTask { runResolverForNoReceiver(info, manager) } - else -> run { - if (receiver is FirQualifiedAccessExpression) { - val calleeReference = receiver.calleeReference - if (calleeReference is FirSuperReference) { - return@run manager.enqueueResolverTask { runResolverForSuperReceiver(info, receiver.typeRef, manager) } - } - } - manager.enqueueResolverTask { runResolverForExpressionReceiver(info, receiver, manager) } - } - } manager.runTasks() return collector } private fun buildCallResolutionContext( info: CallInfo, - collector: CandidateCollector + collector: CandidateCollector, + towerResolverSession: FirTowerResolverSession ): CallResolutionContext { val candidateFactory = CandidateFactory(components, info) val stubReceiverCandidateFactory = @@ -596,7 +63,8 @@ class FirTowerResolver( invokeBuiltinExtensionReceiverCandidateFactory, stubReceiverCandidateFactory, invokeReceiverCollector, - this + this, + towerResolverSession ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolverSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolverSession.kt new file mode 100644 index 00000000000..ac7a13e3eeb --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirTowerResolverSession.kt @@ -0,0 +1,564 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.resolve.calls + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.isCompanion +import org.jetbrains.kotlin.fir.declarations.isInner +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents +import org.jetbrains.kotlin.fir.resolve.scope +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope +import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope +import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef +import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind +import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST + +class FirTowerResolverSession( + val components: BodyResolveComponents, + implicitReceiverValues: List>, +) { + private data class ImplicitReceiver( + val receiver: ImplicitReceiverValue<*>, + val depth: Int, + val usableAsValue: Boolean + ) + + private val session: FirSession get() = components.session + + private val implicitReceivers: List + private val implicitReceiversUsableAsValues: List + + init { + val (implicitReceivers, implicitReceiversUsableAsValues) = prepareImplicitReceivers(implicitReceiverValues) + this.implicitReceivers = implicitReceivers + this.implicitReceiversUsableAsValues = implicitReceiversUsableAsValues + } + + private val localScopes: List = components.localScopes.asReversed() + + private val topLevelScopes: List = + if (components.typeParametersScopes.isEmpty()) + components.fileImportsScope.asReversed() + else + components.typeParametersScopes.asReversed() + components.fileImportsScope.asReversed() + + fun runResolve(manager: TowerResolveManager, info: CallInfo) { + when (val receiver = info.explicitReceiver) { + is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) } + null -> manager.enqueueResolverTask { runResolverForNoReceiver(info, manager) } + else -> run { + if (receiver is FirQualifiedAccessExpression) { + val calleeReference = receiver.calleeReference + if (calleeReference is FirSuperReference) { + return@run manager.enqueueResolverTask { runResolverForSuperReceiver(info, receiver.typeRef, manager) } + } + } + manager.enqueueResolverTask { runResolverForExpressionReceiver(info, receiver, manager) } + } + } + } + + private fun FirScope.toScopeTowerLevel( + extensionReceiver: ReceiverValue? = null, + extensionsOnly: Boolean = false, + noInnerConstructors: Boolean = false + ): ScopeTowerLevel = ScopeTowerLevel( + session, components, this, + extensionReceiver, extensionsOnly, noInnerConstructors + ) + + private fun ReceiverValue.toMemberScopeTowerLevel( + extensionReceiver: ReceiverValue? = null, + implicitExtensionInvokeMode: Boolean = false + ) = MemberScopeTowerLevel( + session, components, this, + extensionReceiver, implicitExtensionInvokeMode, + scopeSession = components.scopeSession + ) + + private suspend fun processQualifierScopes( + manager: TowerResolveManager, + info: CallInfo, qualifierReceiver: QualifierReceiver? + ) { + if (qualifierReceiver == null) return + for ((depth, qualifierScope) in qualifierReceiver.callableScopes().withIndex()) { + manager.processLevel( + qualifierScope.toScopeTowerLevel(noInnerConstructors = true), + info.noStubReceiver(), TowerGroup.Qualifier(depth) + ) + } + } + + private suspend fun processClassifierScope( + manager: TowerResolveManager, + info: CallInfo, qualifierReceiver: QualifierReceiver?, prioritized: Boolean + ) { + if (qualifierReceiver == null) return + if (info.callKind != CallKind.CallableReference && + qualifierReceiver is ClassQualifierReceiver && + qualifierReceiver.classSymbol != qualifierReceiver.originalSymbol + ) return + val scope = qualifierReceiver.classifierScope() ?: return + manager.processLevel( + scope.toScopeTowerLevel(noInnerConstructors = true), info.noStubReceiver(), + if (prioritized) TowerGroup.ClassifierPrioritized else TowerGroup.Classifier + ) + } + + private suspend fun runResolverForQualifierReceiver( + info: CallInfo, + resolvedQualifier: FirResolvedQualifier, + manager: TowerResolveManager + ) { + val qualifierReceiver = createQualifierReceiver(resolvedQualifier, session, components.scopeSession) + + when { + info.isPotentialQualifierPart -> { + processClassifierScope(manager, info, qualifierReceiver, prioritized = true) + processQualifierScopes(manager, info, qualifierReceiver) + } + else -> { + processQualifierScopes(manager, info, qualifierReceiver) + processClassifierScope(manager, info, qualifierReceiver, prioritized = false) + } + } + + if (resolvedQualifier.symbol != null) { + val typeRef = resolvedQualifier.typeRef + // NB: yet built-in Unit is used for "no-value" type + if (info.callKind == CallKind.CallableReference) { + if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) { + runResolverForExpressionReceiver(info, resolvedQualifier, manager) + } + } else { + if (typeRef !is FirImplicitBuiltinTypeRef) { + runResolverForExpressionReceiver(info, resolvedQualifier, manager) + } + } + } + } + + private suspend fun runResolverForNoReceiver( + info: CallInfo, + manager: TowerResolveManager + ) { + manager.processExtensionsThatHideMembers(info, explicitReceiverValue = null) + val nonEmptyLocalScopes = mutableListOf() + manager.processLocalScopesWithNoReceiver(info, nonEmptyLocalScopes) + + val emptyTopLevelScopes = mutableSetOf() + manager.processImplicitReceiversWithNoExplicit(info, nonEmptyLocalScopes, emptyTopLevelScopes) + + manager.processTopLevelScopesNoReceiver(info, emptyTopLevelScopes) + } + + private suspend fun TowerResolveManager.processExtensionsThatHideMembers( + info: CallInfo, + explicitReceiverValue: ReceiverValue? + ) { + val shouldProcessExtensionsBeforeMembers = + info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST + + if (!shouldProcessExtensionsBeforeMembers) return + + for ((index, topLevelScope) in topLevelScopes.withIndex()) { + if (explicitReceiverValue != null) { + processHideMembersLevel(explicitReceiverValue, topLevelScope, info, index, depth = null) + } else { + for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + processHideMembersLevel(implicitReceiverValue, topLevelScope, info, index, depth) + } + } + } + } + + private suspend fun TowerResolveManager.processHideMembersLevel( + receiverValue: ReceiverValue, + topLevelScope: FirScope, + info: CallInfo, + index: Int, + depth: Int? + ) = processLevel( + topLevelScope.toScopeTowerLevel( + extensionReceiver = receiverValue, extensionsOnly = true + ), + info, TowerGroup.TopPrioritized(index).let { if (depth != null) it.Implicit(depth) else it } + ) + + private suspend fun TowerResolveManager.processLocalScopesWithNoReceiver( + info: CallInfo, + nonEmptyLocalScopes: MutableList + ) { + for ((index, localScope) in localScopes.withIndex()) { + val result = processLevel( + localScope.toScopeTowerLevel(), info, TowerGroup.Local(index) + ) + if (result != ProcessorAction.NONE) { + nonEmptyLocalScopes += localScope + } + } + } + + private suspend fun TowerResolveManager.processImplicitReceiversWithNoExplicit( + info: CallInfo, + nonEmptyLocalScopes: MutableList, + emptyTopLevelScopes: MutableSet + ) { + val implicitReceiverValuesWithEmptyScopes = mutableSetOf>() + for ((implicitReceiverValue, depth, usableAsValue) in implicitReceivers) { + // NB: companions are processed via implicitReceiverValues! + val parentGroup = TowerGroup.Implicit(depth) + + if (usableAsValue) { + processCandidatesWithGivenImplicitReceiverAsValue( + implicitReceiverValue, + this, + info, + parentGroup, + implicitReceiverValuesWithEmptyScopes, + nonEmptyLocalScopes, + emptyTopLevelScopes + ) + } + + if (implicitReceiverValue is ImplicitDispatchReceiverValue) { + val scope = implicitReceiverValue.scope(session, components.scopeSession) + if (scope != null) { + processLevel( + FirStaticScope(scope).toScopeTowerLevel(), + info, parentGroup.Static(depth) + ) + } + } + } + } + + private suspend fun processCandidatesWithGivenImplicitReceiverAsValue( + receiver: ImplicitReceiverValue<*>, + manager: TowerResolveManager, + info: CallInfo, + parentGroup: TowerGroup, + implicitReceiverValuesWithEmptyScopes: MutableSet>, + nonEmptyLocalScopes: List, + emptyTopLevelScopes: MutableSet + ) { + val implicitResult = manager.processLevel( + receiver.toMemberScopeTowerLevel(), info, parentGroup.Member + ) + + if (implicitResult == ProcessorAction.NONE) { + implicitReceiverValuesWithEmptyScopes += receiver + } + + for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { + manager.processLevel( + localScope.toScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.Local(localIndex) + ) + } + + for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { + if (implicitDispatchReceiverValue in implicitReceiverValuesWithEmptyScopes) continue + manager.processLevel( + implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.Implicit(dispatchDepth) + ) + } + + for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { + if (topLevelScope in emptyTopLevelScopes) continue + val result = manager.processLevel( + topLevelScope.toScopeTowerLevel(extensionReceiver = receiver), + info, parentGroup.Top(topIndex) + ) + if (result == ProcessorAction.NONE) { + emptyTopLevelScopes += topLevelScope + } + } + } + + private suspend fun TowerResolveManager.processTopLevelScopesNoReceiver( + info: CallInfo, + emptyTopLevelScopes: Collection + ) { + for ((index, topLevelScope) in topLevelScopes.withIndex()) { + // NB: this check does not work for variables + // because we do not search for objects if we have extension receiver + if (info.callKind != CallKind.VariableAccess && topLevelScope in emptyTopLevelScopes) continue + processLevel( + topLevelScope.toScopeTowerLevel(), info, TowerGroup.Top(index) + ) + } + } + + private suspend fun runResolverForExpressionReceiver( + info: CallInfo, + receiver: FirExpression, + manager: TowerResolveManager + ) { + val explicitReceiverValue = ExpressionReceiverValue(receiver) + + manager.processExtensionsThatHideMembers(info, explicitReceiverValue) + manager.processMembersForExplicitReceiver(explicitReceiverValue, info) + + val shouldProcessExplicitReceiverScopeOnly = + info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe() != null + if (shouldProcessExplicitReceiverScopeOnly) { + // Special case (integer literal type) + return + } + + val nonEmptyLocalScopes = mutableListOf() + for ((index, localScope) in localScopes.withIndex()) { + if (manager.processScopeForExplicitReceiver( + localScope, + explicitReceiverValue, + info, + TowerGroup.Local(index) + ) != ProcessorAction.NONE + ) { + nonEmptyLocalScopes += localScope + } + } + + for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + processCombinationOfReceivers(manager, implicitReceiverValue, explicitReceiverValue, info, depth, nonEmptyLocalScopes) + } + + for ((index, topLevelScope) in topLevelScopes.withIndex()) { + manager.processScopeForExplicitReceiver( + topLevelScope, + explicitReceiverValue, + info, + TowerGroup.Top(index) + ) + } + } + + private suspend fun TowerResolveManager.processScopeForExplicitReceiver( + scope: FirScope, + explicitReceiverValue: ExpressionReceiverValue, + info: CallInfo, + towerGroup: TowerGroup, + ): ProcessorAction { + val result = processLevel( + scope.toScopeTowerLevel(extensionReceiver = explicitReceiverValue), + info, towerGroup, ExplicitReceiverKind.EXTENSION_RECEIVER + ) + + processLevelForPropertyWithInvoke( + scope.toScopeTowerLevel(), info, towerGroup + ) + + return result + } + + private suspend fun TowerResolveManager.processMembersForExplicitReceiver( + explicitReceiverValue: ExpressionReceiverValue, + info: CallInfo + ) { + processLevel( + explicitReceiverValue.toMemberScopeTowerLevel(), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER + ) + } + + private suspend fun processCombinationOfReceivers( + manager: TowerResolveManager, + implicitReceiverValue: ImplicitReceiverValue<*>, + explicitReceiverValue: ExpressionReceiverValue, + info: CallInfo, + depth: Int, + nonEmptyLocalScopes: MutableList + ) { + // NB: companions are processed via implicitReceiverValues! + val parentGroup = TowerGroup.Implicit(depth) + + // Member extensions + manager.processLevel( + implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = explicitReceiverValue), + info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER + ) + // properties for invoke on implicit receiver + manager.processLevelForPropertyWithInvoke( + implicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member + ) + + for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) { + manager.processLevelForPropertyWithInvoke( + localScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.Local(localIndex) + ) + } + + for ((implicitDispatchReceiverValue, dispatchDepth) in implicitReceiversUsableAsValues) { + manager.processLevelForPropertyWithInvoke( + implicitDispatchReceiverValue.toMemberScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.Implicit(dispatchDepth) + ) + } + + for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) { + manager.processLevelForPropertyWithInvoke( + topLevelScope.toScopeTowerLevel(extensionReceiver = implicitReceiverValue), + info, parentGroup.Top(topIndex) + ) + } + } + + private suspend fun runResolverForSuperReceiver( + info: CallInfo, + superTypeRef: FirTypeRef, + manager: TowerResolveManager + ) { + val scope = when (superTypeRef) { + is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession) + is FirComposedSuperTypeRef -> FirCompositeScope( + superTypeRef.superTypeRefs.mapNotNullTo(mutableListOf()) { it.type.scope(session, components.scopeSession) } + ) + else -> null + } ?: return + manager.processLevel( + scope.toScopeTowerLevel(), + info, TowerGroup.Member, explicitReceiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER + ) + } + + internal suspend fun runResolverForInvoke( + info: CallInfo, + invokeReceiverValue: ExpressionReceiverValue, + manager: TowerResolveManager + ) { + manager.processLevel( + invokeReceiverValue.toMemberScopeTowerLevel(), + info, TowerGroup.Member, + ExplicitReceiverKind.DISPATCH_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + + for ((index, localScope) in localScopes.withIndex()) { + manager.processLevel( + localScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, TowerGroup.Local(index), + ExplicitReceiverKind.EXTENSION_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + } + + for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + // NB: companions are processed via implicitReceiverValues! + val parentGroup = TowerGroup.Implicit(depth) + manager.processLevel( + implicitReceiverValue.toMemberScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, parentGroup.Member, + ExplicitReceiverKind.EXTENSION_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + } + + for ((index, topLevelScope) in topLevelScopes.withIndex()) { + manager.processLevel( + topLevelScope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), + info, TowerGroup.Top(index), + ExplicitReceiverKind.EXTENSION_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + } + } + + // Here we already know extension receiver for invoke, and it's stated in info as first argument + internal suspend fun runResolverForBuiltinInvokeExtensionWithExplicitArgument( + info: CallInfo, + invokeReceiverValue: ExpressionReceiverValue, + manager: TowerResolveManager + ) { + manager.processLevel( + invokeReceiverValue.toMemberScopeTowerLevel(), + info, TowerGroup.Member, + ExplicitReceiverKind.DISPATCH_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + } + + // Here we don't know extension receiver for invoke, assuming it's one of implicit receivers + internal suspend fun runResolverForBuiltinInvokeExtensionWithImplicitArgument( + info: CallInfo, + invokeReceiverValue: ExpressionReceiverValue, + manager: TowerResolveManager + ) { + for ((implicitReceiverValue, depth) in implicitReceiversUsableAsValues) { + val parentGroup = TowerGroup.Implicit(depth) + manager.processLevel( + invokeReceiverValue.toMemberScopeTowerLevel( + extensionReceiver = implicitReceiverValue, + implicitExtensionInvokeMode = true + ), + info, parentGroup.InvokeExtension, + ExplicitReceiverKind.DISPATCH_RECEIVER, + InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER + ) + } + } + + private companion object { + private fun prepareImplicitReceivers( + implicitReceiverValues: List> + ): Pair, List> { + var depth = 0 + var firstDispatchValue = true + val explicitCompanions = mutableListOf() + val implicitReceiversUsableAsValues = mutableListOf() + val implicitReceivers = implicitReceiverValues.mapNotNull { receiverValue -> + val usableAsValue = when (receiverValue) { + is ImplicitExtensionReceiverValue -> true + is ImplicitDispatchReceiverValue -> { + val symbol = receiverValue.boundSymbol + val klass = symbol.fir as? FirRegularClass + + if (!receiverValue.implicitCompanion && klass?.isCompanion == true) { + explicitCompanions += klass.symbol + } + + if (firstDispatchValue && !receiverValue.inDelegated) { + if (!receiverValue.implicitCompanion && + klass?.isInner == false && + !symbol.classId.isLocal + ) { + firstDispatchValue = false + } + true + } else { + symbol.fir.classKind == ClassKind.OBJECT && !receiverValue.inDelegated + } + } + } + + if (receiverValue is ImplicitDispatchReceiverValue && receiverValue.implicitCompanion && receiverValue.boundSymbol in explicitCompanions) { + null + } else { + ImplicitReceiver(receiverValue, depth++, usableAsValue).also { + if (usableAsValue) { + implicitReceiversUsableAsValues.add(it) + } + } + } + } + + return implicitReceivers to implicitReceiversUsableAsValues + } + + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevelHandler.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevelHandler.kt index bc84946dccb..de65eca1588 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevelHandler.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevelHandler.kt @@ -31,7 +31,8 @@ internal class CallResolutionContext( val invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory?, val stubReceiverCandidateFactory: CandidateFactory?, val invokeReceiverCollector: CandidateCollector?, - val towerResolver: FirTowerResolver + val towerResolver: FirTowerResolver, + val towerResolverSession: FirTowerResolverSession ) { // TODO: Get rid of the property, storing state here looks like a hack internal lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory @@ -47,6 +48,7 @@ internal class LevelHandler( private val resultCollector: CandidateCollector get() = callResolutionContext.resultCollector private val towerResolver: FirTowerResolver get() = callResolutionContext.towerResolver + private val towerResolverSession: FirTowerResolverSession get() = callResolutionContext.towerResolverSession private fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) = manager.enqueueResolverTask(group, task) @@ -203,26 +205,26 @@ internal class LevelHandler( when { invokeBuiltinExtensionMode -> { enqueueResolverTask { - towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument( + towerResolverSession.runResolverForBuiltinInvokeExtensionWithExplicitArgument( invokeFunctionInfo, explicitReceiver, manager ) } } useImplicitReceiverAsBuiltinInvokeArgument -> { enqueueResolverTask { - towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument( + towerResolverSession.runResolverForBuiltinInvokeExtensionWithImplicitArgument( invokeFunctionInfo, explicitReceiver, manager ) } enqueueResolverTask { - towerResolver.runResolverForInvoke( + towerResolverSession.runResolverForInvoke( invokeFunctionInfo, explicitReceiver, manager ) } } else -> { enqueueResolverTask { - towerResolver.runResolverForInvoke( + towerResolverSession.runResolverForInvoke( invokeFunctionInfo, explicitReceiver, manager ) }