From aafde418ccd33f2b688afb1d482391e07c77c478 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 16 Jan 2023 15:57:08 +0100 Subject: [PATCH] K2: store imported static qualifiers in dispatch receiver field This is a partial revert of commit 104fd4c1 #KT-55116 Fixed --- .../resolve/arguments/kt41940.fir.txt | 2 +- .../j+k/FlexiblePrimitiveOverloading.fir.txt | 2 +- .../problems/isAncestor.fir.txt | 4 +- .../FirStandaloneQualifierChecker.kt | 3 +- .../kotlin/fir/backend/ConversionUtils.kt | 4 +- .../kotlin/fir/resolve/calls/Candidate.kt | 1 - .../fir/resolve/calls/CandidateFactory.kt | 2 - .../fir/resolve/calls/ResolutionStages.kt | 3 +- .../fir/resolve/calls/VisibilityUtils.kt | 16 ++--- .../resolve/calls/tower/TowerLevelHandler.kt | 3 - .../fir/resolve/calls/tower/TowerLevels.kt | 59 +++++++------------ 11 files changed, 34 insertions(+), 65 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/kt41940.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/kt41940.fir.txt index 4bf790068f5..9a68a08246c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/kt41940.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/kt41940.fir.txt @@ -1,4 +1,4 @@ FILE: main.kt public final fun test(list: R|kotlin/collections/List|, string: R|kotlin/String|): R|kotlin/Unit| { - R|/Matchers.assertThat|, kotlin/collections/List?>|>(R|/list|, R|/Matchers.hasItem|(R|/string|)) + Q|Matchers|.R|/Matchers.assertThat|, kotlin/collections/List?>|>(R|/list|, Q|Matchers|.R|/Matchers.hasItem|(R|/string|)) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FlexiblePrimitiveOverloading.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FlexiblePrimitiveOverloading.fir.txt index c7939573405..bc9127a1f14 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FlexiblePrimitiveOverloading.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/FlexiblePrimitiveOverloading.fir.txt @@ -1,4 +1,4 @@ FILE: FlexiblePrimitiveOverloading.kt public final fun foo(): R|kotlin/Unit| { - R|java/lang/Integer.getInteger|(String(text), Int(239)) + Q|java/lang/Integer|.R|java/lang/Integer.getInteger|(String(text), Int(239)) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/isAncestor.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/isAncestor.fir.txt index 4ce8c33513a..eb9ebb3b16e 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/isAncestor.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/isAncestor.fir.txt @@ -2,8 +2,8 @@ FILE: test.kt public final fun foo(): R|kotlin/Unit| { lval externalsMap: R|kotlin/collections/MutableMap| = R|kotlin/collections/mutableMapOf|() local final fun test(file: R|java/io/File|): R|kotlin/Unit| { - lval base: R|java/io/File!| = R|your/ContainerUtil.find|(R|/externalsMap|.R|SubstitutionOverride|>|, = find@fun (it: R|java/io/File!|): R|kotlin/Boolean| { - ^ R|my/FileUtil.isAncestor|(R|/it|, R|/file|, Boolean(false)) + lval base: R|java/io/File!| = Q|your/ContainerUtil|.R|your/ContainerUtil.find|(R|/externalsMap|.R|SubstitutionOverride|>|, = find@fun (it: R|java/io/File!|): R|kotlin/Boolean| { + ^ Q|my/FileUtil|.R|my/FileUtil.isAncestor|(R|/it|, R|/file|, Boolean(false)) } ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt index 4a2b9f317aa..8d71b78c0bc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt @@ -22,7 +22,8 @@ import org.jetbrains.kotlin.fir.types.isUnit object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() { override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { val lastQualifiedAccess = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirQualifiedAccess - if (lastQualifiedAccess?.explicitReceiver === expression) return + // Note: qualifier isn't standalone when it's in receiver (SomeClass.foo) or getClass (SomeClass::class) position + if (lastQualifiedAccess?.explicitReceiver === expression || lastQualifiedAccess?.dispatchReceiver === expression) return val lastGetClass = context.getClassCalls.lastOrNull() if (lastGetClass?.argument === expression) return // Note: if it's real Unit, it will be filtered by ClassKind.OBJECT check below diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 955a9f0c4f6..1ee102aa5ac 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -225,9 +225,7 @@ private fun FirCallableSymbol<*>.toSymbolForCall( val fakeOverrideOwnerLookupTag = when { // Static fake overrides isStatic -> { - fir.importedFromObjectOrStaticData?.let { - ConeClassLikeLookupTagImpl(it.objectClassId) - } ?: (explicitReceiver as? FirResolvedQualifier)?.toLookupTag() + ((dispatchReceiver as? FirResolvedQualifier) ?: (explicitReceiver as? FirResolvedQualifier))?.toLookupTag() } // Member fake override or bound callable reference dispatchReceiver !is FirNoReceiverExpression -> { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index 70cadc79165..af94731ea43 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -36,7 +36,6 @@ class Candidate( private val baseSystem: ConstraintStorage, override val callInfo: CallInfo, val originScope: FirScope?, - val importedQualifierForStatic: FirExpression? = null, val isFromCompanionObjectTypeScope: Boolean = false ) : AbstractCandidate() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt index 48af548d5ff..1e1448ff2b4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt @@ -53,7 +53,6 @@ class CandidateFactory private constructor( explicitReceiverKind: ExplicitReceiverKind, scope: FirScope?, dispatchReceiverValue: ReceiverValue? = null, - importedQualifierForStatic: FirExpression? = null, givenExtensionReceiverOptions: List = emptyList(), objectsByName: Boolean = false ): Candidate { @@ -69,7 +68,6 @@ class CandidateFactory private constructor( baseSystem, callInfo, scope, - importedQualifierForStatic, isFromCompanionObjectTypeScope = when (explicitReceiverKind) { ExplicitReceiverKind.EXTENSION_RECEIVER -> givenExtensionReceiverOptions.singleOrNull().isCandidateFromCompanionObjectTypeScope() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 03fd8e1b992..512fe07025c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -544,8 +544,7 @@ internal object CheckVisibility : CheckerStage() { val visible = visibilityChecker.isVisible( declaration, candidate.callInfo, - dispatchReceiverValue = null, - importedQualifierForStatic = null + dispatchReceiverValue = null ) if (!visible) { sink.yieldDiagnostic(VisibilityError) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt index 65bfb3d7724..7a547f8ee08 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/VisibilityUtils.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField import org.jetbrains.kotlin.fir.declarations.utils.isStatic import org.jetbrains.kotlin.fir.declarations.utils.visibility -import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment @@ -28,11 +27,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf fun FirVisibilityChecker.isVisible( declaration: FirMemberDeclaration, callInfo: CallInfo, - dispatchReceiverValue: ReceiverValue?, - importedQualifierForStatic: FirExpression? + dispatchReceiverValue: ReceiverValue? ): Boolean { val staticQualifierForCallable = runIf(declaration is FirCallableDeclaration && declaration.isStatic) { - val explicitReceiver = callInfo.explicitReceiver ?: importedQualifierForStatic + val explicitReceiver = callInfo.explicitReceiver ?: (dispatchReceiverValue as? ExpressionReceiverValue)?.explicitReceiver (explicitReceiver as? FirResolvedQualifier)?.symbol?.fir as? FirRegularClass } return isVisible( @@ -51,21 +49,19 @@ fun FirVisibilityChecker.isVisible( candidate: Candidate ): Boolean { val callInfo = candidate.callInfo - val dispatchReceiverValue = candidate.dispatchReceiverValue - val importedQualifierForStatic = candidate.importedQualifierForStatic - if (!isVisible(declaration, callInfo, dispatchReceiverValue, importedQualifierForStatic)) { + if (!isVisible(declaration, callInfo, candidate.dispatchReceiverValue)) { val dispatchReceiverWithoutSmartCastType = - removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue, candidate.callInfo.session) ?: return false + removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiverValue, candidate.callInfo.session) ?: return false - if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType, importedQualifierForStatic)) return false + if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false candidate.dispatchReceiverValue = dispatchReceiverWithoutSmartCastType } val backingField = declaration.getBackingFieldIfApplicable() if (backingField != null) { - candidate.hasVisibleBackingField = isVisible(backingField, callInfo, dispatchReceiverValue, importedQualifierForStatic) + candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiverValue) } return true diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevelHandler.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevelHandler.kt index f6e0d2097de..3e8714d9cf6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevelHandler.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevelHandler.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower -import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -75,7 +74,6 @@ private class TowerScopeLevelProcessor( override fun consumeCandidate( symbol: FirBasedSymbol<*>, dispatchReceiverValue: ReceiverValue?, - importedQualifierForStatic: FirExpression?, givenExtensionReceiverOptions: List, scope: FirScope, objectsByName: Boolean @@ -87,7 +85,6 @@ private class TowerScopeLevelProcessor( explicitReceiverKind, scope, dispatchReceiverValue, - importedQualifierForStatic, givenExtensionReceiverOptions, objectsByName ), candidateFactory.context diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index f2cca24e8f7..8b0ee900484 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -6,10 +6,11 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup +import org.jetbrains.kotlin.fir.declarations.FirConstructor +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isInner -import org.jetbrains.kotlin.fir.declarations.utils.isStatic -import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier import org.jetbrains.kotlin.fir.resolve.* @@ -25,7 +26,6 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.StandardClassIds.Annotations.HidesMembers import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.runIf enum class ProcessResult { FOUND, SCOPE_EMPTY; @@ -54,7 +54,6 @@ abstract class TowerScopeLevel { fun consumeCandidate( symbol: T, dispatchReceiverValue: ReceiverValue?, - importedQualifierForStatic: FirExpression?, givenExtensionReceiverOptions: List, scope: FirScope, objectsByName: Boolean = false @@ -147,7 +146,6 @@ class MemberScopeTowerLevel( output.consumeCandidate( symbol, dispatchReceiverValue, - importedQualifierForStatic = null, givenExtensionReceiverOptions = emptyList(), scope ) @@ -176,7 +174,7 @@ class MemberScopeTowerLevel( val candidates = mutableListOf>() for (group in overridableGroups) { val visibleCandidates = group.filter { - visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue, importedQualifierForStatic = null) + visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue) } val visibleCandidatesFromSmartcast = visibleCandidates.filter { candidatesMapping.getValue(it) } @@ -212,7 +210,6 @@ class MemberScopeTowerLevel( output.consumeCandidate( candidate, dispatchReceiverValue, - importedQualifierForStatic = null, givenExtensionReceiverOptions, scope ) @@ -330,26 +327,20 @@ class ScopeTowerLevel( fun areThereExtensionReceiverOptions(): Boolean = givenExtensionReceiverOptions.isNotEmpty() - private fun FirCallableDeclaration.importedQualifierForObjectOrStatic(): FirExpression? { - val objectClassId = importedFromObjectOrStaticData?.objectClassId ?: return null - val symbol = session.symbolProvider.getClassLikeSymbolByClassId(objectClassId) - if (symbol is FirRegularClassSymbol) { - return buildResolvedQualifier { - packageFqName = objectClassId.packageFqName - relativeClassFqName = objectClassId.relativeClassName - this.symbol = symbol - }.apply { - resultType = bodyResolveComponents.typeForQualifier(this) - } - } - return null - } - private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? { - if (candidate.fir.isStatic) return null - val importedQualifierReceiver = candidate.fir.importedQualifierForObjectOrStatic() - if (importedQualifierReceiver != null) { - return ExpressionReceiverValue(importedQualifierReceiver) + candidate.fir.importedFromObjectOrStaticData?.let { data -> + val objectClassId = data.objectClassId + val symbol = session.symbolProvider.getClassLikeSymbolByClassId(objectClassId) + if (symbol is FirRegularClassSymbol) { + val resolvedQualifier = buildResolvedQualifier { + packageFqName = objectClassId.packageFqName + relativeClassFqName = objectClassId.relativeClassName + this.symbol = symbol + }.apply { + resultType = bodyResolveComponents.typeForQualifier(this) + } + return ExpressionReceiverValue(resolvedQualifier) + } } if (candidate !is FirBackingFieldSymbol) { @@ -404,22 +395,14 @@ class ScopeTowerLevel( val receiverExpected = withHideMembersOnly || areThereExtensionReceiverOptions() if (candidateReceiverTypeRef == null == receiverExpected) return val dispatchReceiverValue = dispatchReceiverValue(candidate) - val isStatic = candidate.fir.isStatic - val importedQualifierForStatic = runIf(isStatic) { - candidate.fir.importedQualifierForObjectOrStatic() - } - if (dispatchReceiverValue == null && - importedQualifierForStatic == null && - shouldSkipCandidateWithInconsistentExtensionReceiver(candidate) - ) { + if (dispatchReceiverValue == null && shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)) { return } - val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol.takeIf { !isStatic } ?: candidate + val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol ?: candidate @Suppress("UNCHECKED_CAST") processor.consumeCandidate( unwrappedCandidate as T, dispatchReceiverValue, - importedQualifierForStatic, givenExtensionReceiverOptions, scope ) @@ -465,9 +448,7 @@ class ScopeTowerLevel( scope.processClassifiersByName(info.name) { empty = false processor.consumeCandidate( - it, - dispatchReceiverValue = null, - importedQualifierForStatic = null, + it, dispatchReceiverValue = null, givenExtensionReceiverOptions = emptyList(), scope = scope, objectsByName = true