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 62f5d89a8d3..b7a4e185b3e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -73,62 +73,60 @@ class FirCallResolver( fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall): FirFunctionCall { @Suppress("NAME_SHADOWING") val functionCall = if (needTransformArguments) { - components.context.withIncrementedQualifierPartIndex { functionCall.transformExplicitReceiver() } - .also { - components.dataFlowAnalyzer.enterQualifiedAccessExpression() - functionCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent) - } + functionCall.transformExplicitReceiver().also { + components.dataFlowAnalyzer.enterQualifiedAccessExpression() + functionCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent) + } } else { functionCall } - return components.context.withIncrementedQualifierPartIndex { - val name = functionCall.calleeReference.name - val result = collectCandidates(functionCall, name, origin = functionCall.origin) + val name = functionCall.calleeReference.name + val result = collectCandidates(functionCall, name, origin = functionCall.origin) - var forceCandidates: Collection? = null - if (result.candidates.isEmpty()) { - val newResult = collectCandidates(functionCall, name, CallKind.VariableAccess, origin = functionCall.origin) - if (newResult.candidates.isNotEmpty()) { - forceCandidates = newResult.candidates - } + var forceCandidates: Collection? = null + if (result.candidates.isEmpty()) { + val newResult = collectCandidates(functionCall, name, CallKind.VariableAccess, origin = functionCall.origin) + if (newResult.candidates.isNotEmpty()) { + forceCandidates = newResult.candidates } - - val nameReference = createResolvedNamedReference( - functionCall.calleeReference, - name, - result.info, - result.candidates, - result.applicability, - functionCall.explicitReceiver, - expectedCallKind = if (forceCandidates != null) CallKind.VariableAccess else null, - expectedCandidates = forceCandidates - ) - - val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference) - val candidate = (nameReference as? FirNamedReferenceWithCandidate)?.candidate - val resolvedReceiver = functionCall.explicitReceiver - if (candidate != null && resolvedReceiver is FirResolvedQualifier) { - resolvedReceiver.replaceResolvedToCompanionObject(candidate.isFromCompanionObjectTypeScope) - } - - // We need desugaring - val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) { - functionCall.copyAsImplicitInvokeCall { - explicitReceiver = candidate.callInfo.explicitReceiver - dispatchReceiver = candidate.dispatchReceiverExpression() - extensionReceiver = candidate.extensionReceiverExpression() - argumentList = candidate.callInfo.argumentList - } - } else { - resultExpression - } - val typeRef = components.typeFromCallee(resultFunctionCall) - if (typeRef.type is ConeKotlinErrorType) { - resultFunctionCall.resultType = typeRef - } - return@withIncrementedQualifierPartIndex resultFunctionCall } + + val nameReference = createResolvedNamedReference( + functionCall.calleeReference, + name, + result.info, + result.candidates, + result.applicability, + functionCall.explicitReceiver, + expectedCallKind = if (forceCandidates != null) CallKind.VariableAccess else null, + expectedCandidates = forceCandidates + ) + + val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference) + val candidate = (nameReference as? FirNamedReferenceWithCandidate)?.candidate + val resolvedReceiver = functionCall.explicitReceiver + if (candidate != null && resolvedReceiver is FirResolvedQualifier) { + resolvedReceiver.replaceResolvedToCompanionObject(candidate.isFromCompanionObjectTypeScope) + } + + // We need desugaring + val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) { + functionCall.copyAsImplicitInvokeCall { + explicitReceiver = candidate.callInfo.explicitReceiver + dispatchReceiver = candidate.dispatchReceiverExpression() + extensionReceiver = candidate.extensionReceiverExpression() + argumentList = candidate.callInfo.argumentList + } + } else { + resultExpression + } + val typeRef = components.typeFromCallee(resultFunctionCall) + if (typeRef.type is ConeKotlinErrorType) { + resultFunctionCall.resultType = typeRef + } + + return resultFunctionCall } private inline fun Q.transformExplicitReceiver(): Q { @@ -230,116 +228,114 @@ class FirCallResolver( ): FirStatement { val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess - return components.context.withIncrementedQualifierPartIndex { - @Suppress("NAME_SHADOWING") - val qualifiedAccess = qualifiedAccess.transformExplicitReceiver() - val nonFatalDiagnosticFromExpression = (qualifiedAccess as? FirPropertyAccessExpression)?.nonFatalDiagnostics + @Suppress("NAME_SHADOWING") + val qualifiedAccess = qualifiedAccess.transformExplicitReceiver() + val nonFatalDiagnosticFromExpression = (qualifiedAccess as? FirPropertyAccessExpression)?.nonFatalDiagnostics - if (isUsedAsReceiver) { - (qualifiedAccess.explicitReceiver as? FirResolvedQualifier) - ?.continueQualifier( - callee, - qualifiedAccess.source, - qualifiedAccess.typeArguments, - nonFatalDiagnosticFromExpression, - components - ) - ?.let { return it } - } - - var result = collectCandidates(qualifiedAccess, callee.name) - - if (qualifiedAccess.explicitReceiver == null) { - // Even if we successfully resolved to some companion/named object, we should re-try with qualifier resolution - // import D.* - // class A { - // object B - // } - // class D { - // object A - // } - // fun main() { - // A // should resolved to D.A - // A.B // should be resolved to A.B - // } - if (!result.applicability.isSuccess || (isUsedAsReceiver && result.candidates.all { it.symbol is FirRegularClassSymbol })) { - components.resolveRootPartOfQualifier( - callee, qualifiedAccess.source, qualifiedAccess.typeArguments, nonFatalDiagnosticFromExpression, - )?.let { return it } - } - } - - var functionCallExpected = false - if (result.candidates.isEmpty() && qualifiedAccess !is FirFunctionCall) { - val newResult = collectCandidates(qualifiedAccess, callee.name, CallKind.Function) - if (newResult.candidates.isNotEmpty()) { - result = newResult - functionCallExpected = true - } - } - - val reducedCandidates = result.candidates - if (!acceptCandidates(reducedCandidates)) return@withIncrementedQualifierPartIndex qualifiedAccess - - val nameReference = createResolvedNamedReference( - callee, - callee.name, - result.info, - reducedCandidates, - result.applicability, - qualifiedAccess.explicitReceiver, - expectedCallKind = if (functionCallExpected) CallKind.Function else null - ) - - val referencedSymbol = when (nameReference) { - is FirResolvedNamedReference -> nameReference.resolvedSymbol - is FirNamedReferenceWithCandidate -> nameReference.candidateSymbol - else -> null - } - - val diagnostic = when (nameReference) { - is FirErrorReferenceWithCandidate -> nameReference.diagnostic - is FirErrorNamedReference -> nameReference.diagnostic - else -> null - } - - (qualifiedAccess.explicitReceiver as? FirResolvedQualifier)?.replaceResolvedToCompanionObject( - reducedCandidates.isNotEmpty() && reducedCandidates.all { it.isFromCompanionObjectTypeScope } - ) - - when { - referencedSymbol is FirClassLikeSymbol<*> -> { - return@withIncrementedQualifierPartIndex components.buildResolvedQualifierForClass( - referencedSymbol, - qualifiedAccess.source, - qualifiedAccess.typeArguments, - diagnostic, - nonFatalDiagnostics = extractNonFatalDiagnostics( - nameReference.source, - qualifiedAccess.explicitReceiver, - referencedSymbol, - nonFatalDiagnosticFromExpression, - ) - ) - } - referencedSymbol is FirTypeParameterSymbol && referencedSymbol.fir.isReified -> { - return@withIncrementedQualifierPartIndex buildResolvedReifiedParameterReference { - source = nameReference.source - symbol = referencedSymbol - typeRef = typeForReifiedParameterReference(this) - } - } - } - - var resultExpression = qualifiedAccess.transformCalleeReference(StoreNameReference, nameReference) - if (reducedCandidates.size == 1) { - val candidate = reducedCandidates.single() - resultExpression = resultExpression.transformDispatchReceiver(StoreReceiver, candidate.dispatchReceiverExpression()) - resultExpression = resultExpression.transformExtensionReceiver(StoreReceiver, candidate.extensionReceiverExpression()) - } - if (resultExpression is FirExpression) transformer.storeTypeFromCallee(resultExpression) - return@withIncrementedQualifierPartIndex resultExpression + if (isUsedAsReceiver) { + (qualifiedAccess.explicitReceiver as? FirResolvedQualifier) + ?.continueQualifier( + callee, + qualifiedAccess.source, + qualifiedAccess.typeArguments, + nonFatalDiagnosticFromExpression, + components + ) + ?.let { return it } } + + var result = collectCandidates(qualifiedAccess, callee.name) + + if (qualifiedAccess.explicitReceiver == null) { + // Even if we successfully resolved to some companion/named object, we should re-try with qualifier resolution + // import D.* + // class A { + // object B + // } + // class D { + // object A + // } + // fun main() { + // A // should resolved to D.A + // A.B // should be resolved to A.B + // } + if (!result.applicability.isSuccess || (isUsedAsReceiver && result.candidates.all { it.symbol is FirRegularClassSymbol })) { + components.resolveRootPartOfQualifier( + callee, qualifiedAccess.source, qualifiedAccess.typeArguments, nonFatalDiagnosticFromExpression, + )?.let { return it } + } + } + + var functionCallExpected = false + if (result.candidates.isEmpty() && qualifiedAccess !is FirFunctionCall) { + val newResult = collectCandidates(qualifiedAccess, callee.name, CallKind.Function) + if (newResult.candidates.isNotEmpty()) { + result = newResult + functionCallExpected = true + } + } + + val reducedCandidates = result.candidates + if (!acceptCandidates(reducedCandidates)) return qualifiedAccess + + val nameReference = createResolvedNamedReference( + callee, + callee.name, + result.info, + reducedCandidates, + result.applicability, + qualifiedAccess.explicitReceiver, + expectedCallKind = if (functionCallExpected) CallKind.Function else null + ) + + val referencedSymbol = when (nameReference) { + is FirResolvedNamedReference -> nameReference.resolvedSymbol + is FirNamedReferenceWithCandidate -> nameReference.candidateSymbol + else -> null + } + + val diagnostic = when (nameReference) { + is FirErrorReferenceWithCandidate -> nameReference.diagnostic + is FirErrorNamedReference -> nameReference.diagnostic + else -> null + } + + (qualifiedAccess.explicitReceiver as? FirResolvedQualifier)?.replaceResolvedToCompanionObject( + reducedCandidates.isNotEmpty() && reducedCandidates.all { it.isFromCompanionObjectTypeScope } + ) + + when { + referencedSymbol is FirClassLikeSymbol<*> -> { + return components.buildResolvedQualifierForClass( + referencedSymbol, + qualifiedAccess.source, + qualifiedAccess.typeArguments, + diagnostic, + nonFatalDiagnostics = extractNonFatalDiagnostics( + nameReference.source, + qualifiedAccess.explicitReceiver, + referencedSymbol, + nonFatalDiagnosticFromExpression, + ) + ) + } + referencedSymbol is FirTypeParameterSymbol && referencedSymbol.fir.isReified -> { + return buildResolvedReifiedParameterReference { + source = nameReference.source + symbol = referencedSymbol + typeRef = typeForReifiedParameterReference(this) + } + } + } + + var resultExpression = qualifiedAccess.transformCalleeReference(StoreNameReference, nameReference) + if (reducedCandidates.size == 1) { + val candidate = reducedCandidates.single() + resultExpression = resultExpression.transformDispatchReceiver(StoreReceiver, candidate.dispatchReceiverExpression()) + resultExpression = resultExpression.transformExtensionReceiver(StoreReceiver, candidate.extensionReceiverExpression()) + } + if (resultExpression is FirExpression) transformer.storeTypeFromCallee(resultExpression) + return resultExpression } fun resolveCallableReference( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index 6c2438d43b6..5b4cd66d281 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -172,17 +172,6 @@ class BodyResolveContext( } } - var qualifierPartIndexFromEnd: Int = -1 - - inline fun withIncrementedQualifierPartIndex(l: () -> R): R { - qualifierPartIndexFromEnd++ - return try { - l() - } finally { - qualifierPartIndexFromEnd-- - } - } - @PrivateForInline fun replaceTowerDataContext(newContext: FirTowerDataContext) { towerDataContextsForClassParts.currentContext = newContext diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 857f1d53ab4..bcd80a4f0c3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -787,18 +787,16 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform callableReferenceAccess.transformAnnotations(transformer, data) val explicitReceiver = callableReferenceAccess.explicitReceiver - val transformedLHS = context.withIncrementedQualifierPartIndex { - - if (explicitReceiver is FirPropertyAccessExpression) { + val transformedLHS = when (explicitReceiver) { + is FirPropertyAccessExpression -> transformQualifiedAccessExpression( explicitReceiver, ResolutionMode.ContextIndependent, isUsedAsReceiver = true ) as FirExpression - } else { + else -> explicitReceiver?.transformSingle(this, ResolutionMode.ContextIndependent) - }.apply { - if (this is FirResolvedQualifier && callableReferenceAccess.hasQuestionMarkAtLHS) { - replaceIsNullableLHSForCallableReference(true) - } + }.apply { + if (this is FirResolvedQualifier && callableReferenceAccess.hasQuestionMarkAtLHS) { + replaceIsNullableLHSForCallableReference(true) } } @@ -827,7 +825,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform data } - val transformedGetClassCall = context.withIncrementedQualifierPartIndex { + val transformedGetClassCall = run { val argument = getClassCall.argument val replacedArgument: FirExpression = if (argument is FirPropertyAccessExpression)