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 92e56f1fbd1..8c8444c9243 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -265,7 +265,7 @@ class FirCallResolver( implicitReceiverStack.receiversAsReversed(), info, collector = CandidateCollector(this, resolutionStageRunner), - manager = TowerResolveManager(towerResolver), + manager = TowerResolveManager(), ) val bestCandidates = result.bestCandidates() val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED 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 0367af6772d..91cbc8df558 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 @@ -42,7 +42,7 @@ class FirTowerResolver( private val session: FirSession get() = components.session private val collector = CandidateCollector(components, resolutionStageRunner) - private val manager = TowerResolveManager(this) + private val manager = TowerResolveManager() private lateinit var implicitReceivers: List private lateinit var implicitReceiversUsableAsValues: List @@ -546,21 +546,7 @@ class FirTowerResolver( ): CandidateCollector { // TODO: add flag receiver / non-receiver position prepareImplicitReceivers(implicitReceiverValues) - val candidateFactory = CandidateFactory(components, info) - manager.candidateFactory = candidateFactory - if (info.callKind == CallKind.CallableReference && info.stubReceiver != null) { - manager.stubReceiverCandidateFactory = candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver)) - } - manager.resultCollector = collector - if (info.callKind == CallKind.Function) { - manager.invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner) - manager.invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess()) - if (info.explicitReceiver != null) { - with(manager.invokeReceiverCandidateFactory) { - manager.invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null)) - } - } - } + manager.callResolutionContext = buildCallResolutionContext(info, collector) when (val receiver = info.explicitReceiver) { is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver, manager) } @@ -579,6 +565,41 @@ class FirTowerResolver( return collector } + private fun buildCallResolutionContext( + info: CallInfo, + collector: CandidateCollector + ): CallResolutionContext { + val candidateFactory = CandidateFactory(components, info) + val stubReceiverCandidateFactory = + if (info.callKind == CallKind.CallableReference && info.stubReceiver != null) + candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver)) + else + null + + var invokeReceiverCollector: CandidateCollector? = null + var invokeReceiverCandidateFactory: CandidateFactory? = null + var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory? = null + if (info.callKind == CallKind.Function) { + invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner) + invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess()) + if (info.explicitReceiver != null) { + with(invokeReceiverCandidateFactory) { + invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null)) + } + } + } + + return CallResolutionContext( + candidateFactory, + collector, + invokeReceiverCandidateFactory, + invokeBuiltinExtensionReceiverCandidateFactory, + stubReceiverCandidateFactory, + invokeReceiverCollector, + this + ) + } + fun reset() { collector.newDataSet() manager.reset() 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 new file mode 100644 index 00000000000..bc84946dccb --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevelHandler.kt @@ -0,0 +1,290 @@ +/* + * 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.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder +import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal class CallResolutionContext( + val candidateFactory: CandidateFactory, + val resultCollector: CandidateCollector, + val invokeReceiverCandidateFactory: CandidateFactory?, + val invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory?, + val stubReceiverCandidateFactory: CandidateFactory?, + val invokeReceiverCollector: CandidateCollector?, + val towerResolver: FirTowerResolver +) { + // TODO: Get rid of the property, storing state here looks like a hack + internal lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory +} + +internal class LevelHandler( + private val info: CallInfo, + private val explicitReceiverKind: ExplicitReceiverKind, + private val group: TowerGroup, + private val callResolutionContext: CallResolutionContext, + private val manager: TowerResolveManager +) { + + private val resultCollector: CandidateCollector get() = callResolutionContext.resultCollector + private val towerResolver: FirTowerResolver get() = callResolutionContext.towerResolver + + private fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) = + manager.enqueueResolverTask(group, task) + + private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder { + val (name, typeRef) = when (val symbol = candidate.symbol) { + is FirCallableSymbol<*> -> { + symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe()) + } + is FirRegularClassSymbol -> { + symbol.classId.shortClassName to buildResolvedTypeRef { + type = symbol.constructType(emptyArray(), isNullable = false) + } + } + else -> throw AssertionError() + } + return FirQualifiedAccessExpressionBuilder().apply { + calleeReference = FirNamedReferenceWithCandidate( + null, + name, + candidate + ) + dispatchReceiver = candidate.dispatchReceiverExpression() + this.typeRef = typeRef + } + } + + fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction { + var result = ProcessorAction.NONE + val processor = + TowerScopeLevelProcessor( + info.explicitReceiver, + explicitReceiverKind, + resultCollector, + // TODO: performance? + if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) { + callResolutionContext.invokeOnGivenReceiverCandidateFactory + } else callResolutionContext.candidateFactory, + group + ) + when (info.callKind) { + CallKind.VariableAccess -> { + result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) + // TODO: more accurate condition, or process properties/object in some other way + if (!resultCollector.isSuccess() && + (this !is ScopeTowerLevel || this.extensionReceiver == null) + ) { + result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor) + } + } + CallKind.Function -> { + val invokeBuiltinExtensionMode = + invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION + if (!invokeBuiltinExtensionMode) { + result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) + } + if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER || + resultCollector.isSuccess() + ) { + return result + } + + val invokeReceiverProcessor = TowerScopeLevelProcessor( + info.explicitReceiver, + explicitReceiverKind, + callResolutionContext.invokeReceiverCollector!!, + if (invokeBuiltinExtensionMode) callResolutionContext.invokeBuiltinExtensionReceiverCandidateFactory!! + else callResolutionContext.invokeReceiverCandidateFactory!!, + group + ) + callResolutionContext.invokeReceiverCollector.newDataSet() + result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor) + if (this !is ScopeTowerLevel || this.extensionReceiver == null) { + result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor) + } + + if (callResolutionContext.invokeReceiverCollector.isSuccess()) { + processInvokeReceiversCandidates(invokeBuiltinExtensionMode) + } + } + CallKind.CallableReference -> { + val stubReceiver = info.stubReceiver + if (stubReceiver != null) { + val stubReceiverValue = ExpressionReceiverValue(stubReceiver) + val stubProcessor = TowerScopeLevelProcessor( + info.explicitReceiver, + if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) { + ExplicitReceiverKind.DISPATCH_RECEIVER + } else { + ExplicitReceiverKind.EXTENSION_RECEIVER + }, + resultCollector, + callResolutionContext.stubReceiverCandidateFactory!!, group + ) + val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue) + with(towerLevelWithStubReceiver) { + result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor) + result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor) + } + // NB: we don't perform this for implicit Unit + if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) { + result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) + result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) + } + } else { + result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) + result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) + } + } + else -> { + throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}") + } + } + return result + } + + private fun processInvokeReceiversCandidates(invokeBuiltinExtensionMode: Boolean) { + for (invokeReceiverCandidate in callResolutionContext.invokeReceiverCollector!!.bestCandidates()) { + val symbol = invokeReceiverCandidate.symbol + if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue + + val isExtensionFunctionType = + (symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true + + if (invokeBuiltinExtensionMode && !isExtensionFunctionType) { + continue + } + + val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression() + val useImplicitReceiverAsBuiltinInvokeArgument = + !invokeBuiltinExtensionMode && isExtensionFunctionType && + invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER + + val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let { + if (!invokeBuiltinExtensionMode) { + it.extensionReceiver = extensionReceiverExpression + // NB: this should fix problem in DFA (KT-36014) + it.explicitReceiver = info.explicitReceiver + it.safe = info.isSafeCall + } + towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it.build()) + } + + val invokeFunctionInfo = + info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let { + when { + invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!) + else -> it + } + } + + val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression) + callResolutionContext.invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo) + when { + invokeBuiltinExtensionMode -> { + enqueueResolverTask { + towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument( + invokeFunctionInfo, explicitReceiver, manager + ) + } + } + useImplicitReceiverAsBuiltinInvokeArgument -> { + enqueueResolverTask { + towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument( + invokeFunctionInfo, explicitReceiver, manager + ) + } + enqueueResolverTask { + towerResolver.runResolverForInvoke( + invokeFunctionInfo, explicitReceiver, manager + ) + } + } + else -> { + enqueueResolverTask { + towerResolver.runResolverForInvoke( + invokeFunctionInfo, explicitReceiver, manager + ) + } + } + } + } + } +} + +private class TowerScopeLevelProcessor( + val explicitReceiver: FirExpression?, + val explicitReceiverKind: ExplicitReceiverKind, + val resultCollector: CandidateCollector, + val candidateFactory: CandidateFactory, + val group: TowerGroup +) : TowerScopeLevel.TowerScopeLevelProcessor> { + override fun consumeCandidate( + symbol: AbstractFirBasedSymbol<*>, + dispatchReceiverValue: ReceiverValue?, + implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, + builtInExtensionFunctionReceiverValue: ReceiverValue? + ) { + // Check explicit extension receiver for default package members + if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null && + (implicitExtensionReceiverValue == null) != (explicitReceiver == null) && + explicitReceiver !is FirResolvedQualifier && + symbol.callableId.packageName.startsWith(defaultPackage) + ) { + val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe() + ?: implicitExtensionReceiverValue?.type as? ConeClassLikeType + if (extensionReceiverType != null) { + val declarationReceiverTypeRef = + (symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef + val declarationReceiverType = declarationReceiverTypeRef?.type + if (declarationReceiverType is ConeClassLikeType) { + if (!AbstractTypeChecker.isSubtypeOf( + candidateFactory.bodyResolveComponents.inferenceComponents.ctx, + extensionReceiverType, + declarationReceiverType.lookupTag.constructClassType( + declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(), + isNullable = true + ) + ) + ) { + return + } + } + } + } + // --- + resultCollector.consumeCandidate( + group, candidateFactory.createCandidate( + symbol, + explicitReceiverKind, + dispatchReceiverValue, + implicitExtensionReceiverValue, + builtInExtensionFunctionReceiverValue + ) + ) + } + + companion object { + val defaultPackage = Name.identifier("kotlin") + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt index ec7a9e9fa47..d95d61756cd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt @@ -5,294 +5,24 @@ package org.jetbrains.kotlin.fir.resolve.calls -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier -import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder -import org.jetbrains.kotlin.fir.resolve.constructType -import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo -import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.scopes.ProcessorAction -import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind -import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* import kotlin.coroutines.* -class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) { +class TowerResolveManager internal constructor() { private val queue = PriorityQueue() - lateinit var candidateFactory: CandidateFactory + // TODO: Get rid of the property (it should be passed in a different way) + internal lateinit var callResolutionContext: CallResolutionContext - lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory - - lateinit var invokeReceiverCandidateFactory: CandidateFactory - - lateinit var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory - - lateinit var stubReceiverCandidateFactory: CandidateFactory - - lateinit var resultCollector: CandidateCollector - - lateinit var invokeReceiverCollector: CandidateCollector - - private class TowerScopeLevelProcessor( - val explicitReceiver: FirExpression?, - val explicitReceiverKind: ExplicitReceiverKind, - val resultCollector: CandidateCollector, - val candidateFactory: CandidateFactory, - val group: TowerGroup - ) : TowerScopeLevel.TowerScopeLevelProcessor> { - override fun consumeCandidate( - symbol: AbstractFirBasedSymbol<*>, - dispatchReceiverValue: ReceiverValue?, - implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, - builtInExtensionFunctionReceiverValue: ReceiverValue? - ) { - // Check explicit extension receiver for default package members - if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null && - (implicitExtensionReceiverValue == null) != (explicitReceiver == null) && - explicitReceiver !is FirResolvedQualifier && - symbol.callableId.packageName.startsWith(defaultPackage) - ) { - val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe() - ?: implicitExtensionReceiverValue?.type as? ConeClassLikeType - if (extensionReceiverType != null) { - val declarationReceiverTypeRef = - (symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef - val declarationReceiverType = declarationReceiverTypeRef?.type - if (declarationReceiverType is ConeClassLikeType) { - if (!AbstractTypeChecker.isSubtypeOf( - candidateFactory.bodyResolveComponents.inferenceComponents.ctx, - extensionReceiverType, - declarationReceiverType.lookupTag.constructClassType( - declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(), - isNullable = true - ) - ) - ) { - return - } - } - } - } - // --- - resultCollector.consumeCandidate( - group, candidateFactory.createCandidate( - symbol, - explicitReceiverKind, - dispatchReceiverValue, - implicitExtensionReceiverValue, - builtInExtensionFunctionReceiverValue - ) - ) - } - - companion object { - val defaultPackage = Name.identifier("kotlin") - } - } - - - private inner class LevelHandler( - val info: CallInfo, - val explicitReceiverKind: ExplicitReceiverKind, - val group: TowerGroup - ) { - private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder { - val (name, typeRef) = when (val symbol = candidate.symbol) { - is FirCallableSymbol<*> -> { - symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe()) - } - is FirRegularClassSymbol -> { - symbol.classId.shortClassName to buildResolvedTypeRef { - type = symbol.constructType(emptyArray(), isNullable = false) - } - } - else -> throw AssertionError() - } - return FirQualifiedAccessExpressionBuilder().apply { - calleeReference = FirNamedReferenceWithCandidate( - null, - name, - candidate - ) - dispatchReceiver = candidate.dispatchReceiverExpression() - this.typeRef = typeRef - } - } - - fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction { - var result = ProcessorAction.NONE - val processor = - TowerScopeLevelProcessor( - info.explicitReceiver, - explicitReceiverKind, - resultCollector, - // TODO: performance? - if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) { - invokeOnGivenReceiverCandidateFactory - } else candidateFactory, - group - ) - when (info.callKind) { - CallKind.VariableAccess -> { - result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) - // TODO: more accurate condition, or process properties/object in some other way - if (!resultCollector.isSuccess() && - (this !is ScopeTowerLevel || this.extensionReceiver == null) - ) { - result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor) - } - } - CallKind.Function -> { - val invokeBuiltinExtensionMode = - invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION - if (!invokeBuiltinExtensionMode) { - result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) - } - if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER || - resultCollector.isSuccess() - ) { - return result - } - - val invokeReceiverProcessor = TowerScopeLevelProcessor( - info.explicitReceiver, - explicitReceiverKind, - invokeReceiverCollector, - if (invokeBuiltinExtensionMode) invokeBuiltinExtensionReceiverCandidateFactory - else invokeReceiverCandidateFactory, - group - ) - invokeReceiverCollector.newDataSet() - result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor) - if (this !is ScopeTowerLevel || this.extensionReceiver == null) { - result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor) - } - - if (invokeReceiverCollector.isSuccess()) { - processInvokeReceiversCandidates(invokeBuiltinExtensionMode) - } - } - CallKind.CallableReference -> { - val stubReceiver = info.stubReceiver - if (stubReceiver != null) { - val stubReceiverValue = ExpressionReceiverValue(stubReceiver) - val stubProcessor = TowerScopeLevelProcessor( - info.explicitReceiver, - if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) { - ExplicitReceiverKind.DISPATCH_RECEIVER - } else { - ExplicitReceiverKind.EXTENSION_RECEIVER - }, - resultCollector, - stubReceiverCandidateFactory, group - ) - val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue) - with(towerLevelWithStubReceiver) { - result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor) - result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor) - } - // NB: we don't perform this for implicit Unit - if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) { - result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) - result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) - } - } else { - result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor) - result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor) - } - } - else -> { - throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}") - } - } - return result - } - - private fun processInvokeReceiversCandidates(invokeBuiltinExtensionMode: Boolean) { - for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) { - val symbol = invokeReceiverCandidate.symbol - if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue - - val isExtensionFunctionType = - (symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true - - if (invokeBuiltinExtensionMode && !isExtensionFunctionType) { - continue - } - - val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression() - val useImplicitReceiverAsBuiltinInvokeArgument = - !invokeBuiltinExtensionMode && isExtensionFunctionType && - invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER - - val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let { - if (!invokeBuiltinExtensionMode) { - it.extensionReceiver = extensionReceiverExpression - // NB: this should fix problem in DFA (KT-36014) - it.explicitReceiver = info.explicitReceiver - it.safe = info.isSafeCall - } - towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it.build()) - } - - val invokeFunctionInfo = - info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let { - when { - invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!) - else -> it - } - } - - val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression) - invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo) - when { - invokeBuiltinExtensionMode -> { - enqueueResolverTask { - towerResolver.runResolverForBuiltinInvokeExtensionWithExplicitArgument( - invokeFunctionInfo, explicitReceiver, this@TowerResolveManager - ) - } - } - useImplicitReceiverAsBuiltinInvokeArgument -> { - enqueueResolverTask { - towerResolver.runResolverForBuiltinInvokeExtensionWithImplicitArgument( - invokeFunctionInfo, explicitReceiver, this@TowerResolveManager - ) - } - enqueueResolverTask { - towerResolver.runResolverForInvoke( - invokeFunctionInfo, explicitReceiver, this@TowerResolveManager - ) - } - } - else -> { - enqueueResolverTask { - towerResolver.runResolverForInvoke( - invokeFunctionInfo, explicitReceiver, this@TowerResolveManager - ) - } - } - } - } - } - } + private fun isSuccess() = callResolutionContext.resultCollector.isSuccess() fun reset() { queue.clear() } - private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine { queue += SuspendedResolverTask(it, group) } private suspend fun requestGroup(requested: TowerGroup) { @@ -316,16 +46,15 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow ): ProcessorAction { requestGroup(group) - val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) { + val result = with(LevelHandler(callInfo, explicitReceiverKind, group, callResolutionContext, this)) { towerLevel.handleLevel(invokeResolveMode) } - if (resultCollector.isSuccess()) stopResolverTask() + if (isSuccess()) stopResolverTask() return result } - suspend fun processLevelForPropertyWithInvoke( towerLevel: SessionBasedTowerLevel, callInfo: CallInfo, @@ -364,7 +93,7 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow fun runTasks() { while (queue.isNotEmpty()) { queue.poll().continuation.resume(Unit) - if (resultCollector.isSuccess()) return + if (isSuccess()) return } } }