K2: don't use dispatch receiver to store imported static qualifiers

Related to KT-53441
This commit is contained in:
Mikhail Glukhikh
2022-11-08 18:07:26 +01:00
committed by Space Team
parent 7205a90d9d
commit 104fd4c14d
11 changed files with 128 additions and 85 deletions
@@ -1,4 +1,4 @@
FILE: main.kt
public final fun test(list: R|kotlin/collections/List<kotlin/String>|, string: R|kotlin/String|): R|kotlin/Unit| {
Q|Matchers|.R|/Matchers.assertThat|<R|ft<kotlin/collections/List<kotlin/String>, kotlin/collections/List<kotlin/String>?>|>(R|<local>/list|, Q|Matchers|.R|/Matchers.hasItem|<R|kotlin/String!|>(R|<local>/string|))
R|/Matchers.assertThat|<R|ft<kotlin/collections/List<kotlin/String>, kotlin/collections/List<kotlin/String>?>|>(R|<local>/list|, R|/Matchers.hasItem|<R|kotlin/String!|>(R|<local>/string|))
}
@@ -1,4 +1,4 @@
FILE: FlexiblePrimitiveOverloading.kt
public final fun foo(): R|kotlin/Unit| {
Q|java/lang/Integer|.R|java/lang/Integer.getInteger|(String(text), Int(239))
R|java/lang/Integer.getInteger|(String(text), Int(239))
}
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectOrStaticData
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -227,26 +228,24 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
isDelegate: Boolean = false,
isReference: Boolean = false
): IrSymbol? {
val dispatchReceiverType = when (dispatchReceiver) {
val fakeOverrideOwnerLookupTag = fir.importedFromObjectOrStaticData.takeIf { isStatic }?.let {
ConeClassLikeLookupTagImpl(it.objectClassId)
} ?: when (dispatchReceiver) {
is FirNoReceiverExpression -> {
val containingClass = containingClassLookupTag()
if (containingClass != null && containingClass.classId != StandardClassIds.Any) {
// Make sure that symbol is not extension and is not from inline class
((explicitReceiver as? FirResolvedQualifier)?.symbol as? FirClassSymbol)?.defaultType()
((explicitReceiver as? FirResolvedQualifier)?.symbol as? FirClassSymbol)?.toLookupTag()
} else {
null
}
}
is FirResolvedQualifier -> {
if (isStatic) (dispatchReceiver.symbol as? FirClassSymbol)?.defaultType() else dispatchReceiver.typeRef.coneType
}
else -> {
dispatchReceiver.typeRef.coneType
if (isStatic && dispatchReceiver is FirResolvedQualifier) (dispatchReceiver.symbol as? FirClassSymbol)?.toLookupTag()
else dispatchReceiver.typeRef.coneType.let { it.findClassRepresentation(it, declarationStorage.session) }
}
}
val dispatchReceiverLookupTag = dispatchReceiverType?.findClassRepresentation(dispatchReceiverType, declarationStorage.session)
return when (this) {
is FirSimpleSyntheticPropertySymbol -> {
@@ -255,7 +254,7 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
} else {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
if (isReference) {
declarationStorage.getIrPropertySymbol(this, dispatchReceiverLookupTag)
declarationStorage.getIrPropertySymbol(this, fakeOverrideOwnerLookupTag)
} else {
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
@@ -270,8 +269,8 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
}
}
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this, dispatchReceiverLookupTag)
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this, dispatchReceiverLookupTag)
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this, fakeOverrideOwnerLookupTag)
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this, fakeOverrideOwnerLookupTag)
is FirFieldSymbol -> declarationStorage.getIrFieldSymbol(this)
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
is FirDelegateFieldSymbol -> declarationStorage.getIrDelegateFieldSymbol(this)
@@ -431,13 +431,13 @@ class Fir2IrDeclarationStorage(
fun getCachedIrFunction(
function: FirSimpleFunction,
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
signatureCalculator: () -> IdSignature?
): IrSimpleFunction? {
if (function.visibility == Visibilities.Local) {
return localStorage.getLocalFunction(function)
}
return getCachedIrCallable(function, dispatchReceiverLookupTag, functionCache, signatureCalculator) { signature ->
return getCachedIrCallable(function, fakeOverrideOwnerLookupTag, functionCache, signatureCalculator) { signature ->
symbolTable.referenceSimpleFunctionIfAny(signature)?.owner
}
}
@@ -470,7 +470,7 @@ class Fir2IrDeclarationStorage(
return createIrFunction(
function,
irParent,
containingClass = function.containingClassLookupTag(),
fakeOverrideOwnerLookupTag = function.containingClassLookupTag(),
isLocal = isLocal,
forceTopLevelPrivate = forceTopLevelPrivate
)
@@ -482,7 +482,7 @@ class Fir2IrDeclarationStorage(
thisReceiverOwner: IrClass? = irParent as? IrClass,
predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
containingClass: ConeClassLikeLookupTag? = null,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
forceTopLevelPrivate: Boolean = false,
): IrSimpleFunction = convertCatching(function) {
val simpleFunction = function as? FirSimpleFunction
@@ -513,7 +513,7 @@ class Fir2IrDeclarationStorage(
function.dispatchReceiverType?.isPrimitive != true && function.containerSource == null &&
updatedOrigin != IrDeclarationOrigin.FAKE_OVERRIDE && !function.isOverride
) {
signatureComposer.composeSignature(function, containingClass, forceTopLevelPrivate)
signatureComposer.composeSignature(function, fakeOverrideOwnerLookupTag, forceTopLevelPrivate)
}
if (irParent is Fir2IrLazyClass && signature != null) {
// For private functions signature is null, fallback to non-lazy function
@@ -670,14 +670,14 @@ class Fir2IrDeclarationStorage(
startOffset: Int,
endOffset: Int,
dontUseSignature: Boolean = false,
containingClass: ConeClassLikeLookupTag? = null,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor,
forceTopLevelPrivate: Boolean = false,
): IrSimpleFunction = convertCatching(propertyAccessor ?: property) {
val prefix = if (isSetter) "set" else "get"
val signature =
runUnless(dontUseSignature) {
signatureComposer.composeAccessorSignature(property, isSetter, containingClass, forceTopLevelPrivate)
signatureComposer.composeAccessorSignature(property, isSetter, fakeOverrideOwnerLookupTag, forceTopLevelPrivate)
}
val containerSource = (correspondingProperty as? IrProperty)?.containerSource
return declareIrAccessor(
@@ -811,7 +811,7 @@ class Fir2IrDeclarationStorage(
createIrProperty(
field.toStubProperty(),
irParent,
containingClass = containingClassId?.let { ConeClassLikeLookupTagImpl(it) }
fakeOverrideOwnerLookupTag = containingClassId?.let { ConeClassLikeLookupTagImpl(it) }
)
}
}
@@ -839,7 +839,7 @@ class Fir2IrDeclarationStorage(
thisReceiverOwner: IrClass? = irParent as? IrClass,
predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
containingClass: ConeClassLikeLookupTag? = (irParent as? IrClass)?.classId?.let { ConeClassLikeLookupTagImpl(it) },
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = (irParent as? IrClass)?.classId?.let { ConeClassLikeLookupTagImpl(it) },
forceTopLevelPrivate: Boolean = false,
): IrProperty = convertCatching(property) {
val origin =
@@ -853,7 +853,7 @@ class Fir2IrDeclarationStorage(
property.dispatchReceiverType?.isPrimitive != true && property.containerSource == null &&
origin != IrDeclarationOrigin.FAKE_OVERRIDE && !property.isOverride
) {
signatureComposer.composeSignature(property, containingClass, forceTopLevelPrivate)
signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag, forceTopLevelPrivate)
}
if (irParent is Fir2IrLazyClass && signature != null) {
// For private functions signature is null, fallback to non-lazy property
@@ -928,7 +928,7 @@ class Fir2IrDeclarationStorage(
else -> origin
},
startOffset, endOffset,
dontUseSignature = signature == null, containingClass,
dontUseSignature = signature == null, fakeOverrideOwnerLookupTag,
property.unwrapFakeOverrides().getter,
forceTopLevelPrivate = forceTopLevelPrivate,
)
@@ -941,7 +941,7 @@ class Fir2IrDeclarationStorage(
else -> origin
},
startOffset, endOffset,
dontUseSignature = signature == null, containingClass,
dontUseSignature = signature == null, fakeOverrideOwnerLookupTag,
property.unwrapFakeOverrides().setter,
forceTopLevelPrivate = forceTopLevelPrivate,
)
@@ -958,22 +958,22 @@ class Fir2IrDeclarationStorage(
fun getCachedIrProperty(
property: FirProperty,
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
signatureCalculator: () -> IdSignature?
): IrProperty? {
return getCachedIrCallable(property, dispatchReceiverLookupTag, propertyCache, signatureCalculator) { signature ->
return getCachedIrCallable(property, fakeOverrideOwnerLookupTag, propertyCache, signatureCalculator) { signature ->
symbolTable.referencePropertyIfAny(signature)?.owner
}
}
private inline fun <reified FC : FirCallableDeclaration, reified IC : IrDeclaration> getCachedIrCallable(
declaration: FC,
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
cache: MutableMap<FC, IC>,
signatureCalculator: () -> IdSignature?,
referenceIfAny: (IdSignature) -> IC?
): IC? {
val isFakeOverride = dispatchReceiverLookupTag != null && dispatchReceiverLookupTag != declaration.containingClassLookupTag()
val isFakeOverride = fakeOverrideOwnerLookupTag != null && fakeOverrideOwnerLookupTag != declaration.containingClassLookupTag()
if (!isFakeOverride) {
cache[declaration]?.let { return it }
}
@@ -1238,7 +1238,7 @@ class Fir2IrDeclarationStorage(
val fir = firConstructorSymbol.fir
return getIrCallableSymbol(
firConstructorSymbol,
dispatchReceiverLookupTag = null,
fakeOverrideOwnerLookupTag = null,
getCachedIrDeclaration = { constructor: FirConstructor, _, calculator -> getCachedIrConstructor(constructor, calculator) },
createIrDeclaration = { parent, origin ->
createIrConstructor(fir, parent as IrClass, predefinedOrigin = origin, forceTopLevelPrivate = forceTopLevelPrivate)
@@ -1265,7 +1265,7 @@ class Fir2IrDeclarationStorage(
fun getIrFunctionSymbol(
firFunctionSymbol: FirFunctionSymbol<*>,
dispatchReceiverLookupTag: ConeClassLikeLookupTag? = null,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
forceTopLevelPrivate: Boolean = false,
): IrFunctionSymbol {
return when (val fir = firFunctionSymbol.fir) {
@@ -1277,20 +1277,20 @@ class Fir2IrDeclarationStorage(
createIrFunction(fir, irParent, predefinedOrigin = declarationOrigin).symbol
}
is FirSimpleFunction -> {
val unmatchedReceiver = dispatchReceiverLookupTag != firFunctionSymbol.containingClassLookupTag()
val unmatchedReceiver = fakeOverrideOwnerLookupTag != firFunctionSymbol.containingClassLookupTag()
if (unmatchedReceiver) {
generateLazyFakeOverrides(fir.name, dispatchReceiverLookupTag)
generateLazyFakeOverrides(fir.name, fakeOverrideOwnerLookupTag)
}
val originalSymbol = getIrCallableSymbol(
firFunctionSymbol,
dispatchReceiverLookupTag,
fakeOverrideOwnerLookupTag,
getCachedIrDeclaration = ::getCachedIrFunction,
createIrDeclaration = { parent, origin ->
createIrFunction(
fir, parent,
predefinedOrigin = origin,
forceTopLevelPrivate = forceTopLevelPrivate,
containingClass = dispatchReceiverLookupTag,
fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag,
)
},
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
@@ -1298,9 +1298,9 @@ class Fir2IrDeclarationStorage(
},
forceTopLevelPrivate = forceTopLevelPrivate
) as IrFunctionSymbol
if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) {
if (unmatchedReceiver && fakeOverrideOwnerLookupTag is ConeClassLookupTagWithFixedSymbol) {
val originalFunction = originalSymbol.owner as IrSimpleFunction
dispatchReceiverLookupTag.findIrFakeOverride(fir.name, originalFunction) as IrFunctionSymbol? ?: originalSymbol
fakeOverrideOwnerLookupTag.findIrFakeOverride(fir.name, originalFunction) as IrFunctionSymbol? ?: originalSymbol
} else {
originalSymbol
}
@@ -1338,7 +1338,7 @@ class Fir2IrDeclarationStorage(
fun getIrPropertySymbol(
firPropertySymbol: FirPropertySymbol,
dispatchReceiverLookupTag: ConeClassLikeLookupTag? = null,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
forceTopLevelPrivate: Boolean = false,
): IrSymbol {
val fir = firPropertySymbol.fir
@@ -1346,19 +1346,19 @@ class Fir2IrDeclarationStorage(
return localStorage.getDelegatedProperty(fir)?.symbol ?: getIrVariableSymbol(fir)
}
val containingClassLookupTag = firPropertySymbol.containingClassLookupTag()
val unmatchedReceiver = dispatchReceiverLookupTag != containingClassLookupTag
val unmatchedReceiver = fakeOverrideOwnerLookupTag != containingClassLookupTag
if (unmatchedReceiver) {
generateLazyFakeOverrides(fir.name, dispatchReceiverLookupTag)
generateLazyFakeOverrides(fir.name, fakeOverrideOwnerLookupTag)
}
fun ConeClassLikeLookupTag?.getIrCallableSymbol() = getIrCallableSymbol(
firPropertySymbol,
dispatchReceiverLookupTag = this,
fakeOverrideOwnerLookupTag = this,
getCachedIrDeclaration = ::getCachedIrProperty,
createIrDeclaration = { parent, origin ->
createIrProperty(
fir, parent, predefinedOrigin = origin, forceTopLevelPrivate = forceTopLevelPrivate,
containingClass = dispatchReceiverLookupTag,
fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag,
)
},
createIrLazyDeclaration = { signature, lazyParent, declarationOrigin ->
@@ -1367,7 +1367,7 @@ class Fir2IrDeclarationStorage(
forceTopLevelPrivate = forceTopLevelPrivate
)
val originalSymbol = dispatchReceiverLookupTag.getIrCallableSymbol()
val originalSymbol = fakeOverrideOwnerLookupTag.getIrCallableSymbol()
val originalProperty = originalSymbol.owner as IrProperty
fun IrProperty.isIllegalFakeOverride(): Boolean {
@@ -1379,7 +1379,7 @@ class Fir2IrDeclarationStorage(
return false
}
if (dispatchReceiverLookupTag != null &&
if (fakeOverrideOwnerLookupTag != null &&
firPropertySymbol is FirSyntheticPropertySymbol &&
originalProperty.isIllegalFakeOverride()
) {
@@ -1387,8 +1387,8 @@ class Fir2IrDeclarationStorage(
return containingClassLookupTag.getIrCallableSymbol()
}
return if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) {
dispatchReceiverLookupTag.findIrFakeOverride(fir.name, originalProperty) as IrPropertySymbol
return if (unmatchedReceiver && fakeOverrideOwnerLookupTag is ConeClassLookupTagWithFixedSymbol) {
fakeOverrideOwnerLookupTag.findIrFakeOverride(fir.name, originalProperty) as IrPropertySymbol
} else {
originalSymbol
}
@@ -1429,8 +1429,8 @@ class Fir2IrDeclarationStorage(
}?.symbol
}
private fun generateLazyFakeOverrides(name: Name, dispatchReceiverLookupTag: ConeClassLikeLookupTag?) {
val firClassSymbol = dispatchReceiverLookupTag?.toSymbol(session) as? FirClassSymbol
private fun generateLazyFakeOverrides(name: Name, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?) {
val firClassSymbol = fakeOverrideOwnerLookupTag?.toSymbol(session) as? FirClassSymbol
if (firClassSymbol != null) {
val irClass = classifierStorage.getIrClassSymbol(firClassSymbol).owner
if (irClass is Fir2IrLazyClass) {
@@ -1445,7 +1445,7 @@ class Fir2IrDeclarationStorage(
I : IrSymbolOwner,
> getIrCallableSymbol(
firSymbol: FS,
dispatchReceiverLookupTag: ConeClassLikeLookupTag?,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
getCachedIrDeclaration: (firDeclaration: F, dispatchReceiverLookupTag: ConeClassLikeLookupTag?, () -> IdSignature?) -> I?,
createIrDeclaration: (parent: IrDeclarationParent?, origin: IrDeclarationOrigin) -> I,
createIrLazyDeclaration: (signature: IdSignature, lazyOwner: IrDeclarationParent, origin: IrDeclarationOrigin) -> I,
@@ -1453,9 +1453,9 @@ class Fir2IrDeclarationStorage(
): IrSymbol {
val fir = firSymbol.fir as F
val irParent by lazy { findIrParent(fir) }
val signature by lazy { signatureComposer.composeSignature(fir, dispatchReceiverLookupTag, forceTopLevelPrivate) }
val signature by lazy { signatureComposer.composeSignature(fir, fakeOverrideOwnerLookupTag, forceTopLevelPrivate) }
synchronized(symbolTable.lock) {
getCachedIrDeclaration(fir, dispatchReceiverLookupTag.takeIf { it !is ConeClassLookupTagWithFixedSymbol }) {
getCachedIrDeclaration(fir, fakeOverrideOwnerLookupTag.takeIf { it !is ConeClassLookupTagWithFixedSymbol }) {
// Parent calculation provokes declaration calculation for some members from IrBuiltIns
@Suppress("UNUSED_EXPRESSION") irParent
signature
@@ -212,7 +212,7 @@ class DelegatedMemberGenerator(
val delegateFunction =
declarationStorage.createIrFunction(
delegateOverride, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER,
containingClass = firSubClass.symbol.toLookupTag()
fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag()
)
val baseSymbols = mutableListOf<FirNamedFunctionSymbol>()
// the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their
@@ -293,7 +293,7 @@ class DelegatedMemberGenerator(
val delegateProperty =
declarationStorage.createIrProperty(
firDelegateProperty, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER,
containingClass = firSubClass.symbol.toLookupTag()
fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag()
)
// the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their
// overridden symbols, otherwise in some cases they will be left in inconsistent state leading to the errors in IR
@@ -36,6 +36,7 @@ class Candidate(
private val baseSystem: ConstraintStorage,
override val callInfo: CallInfo,
val originScope: FirScope?,
val importedQualifierForStatic: FirExpression? = null,
val isFromCompanionObjectTypeScope: Boolean = false
) : AbstractCandidate() {
@@ -49,6 +49,7 @@ class CandidateFactory private constructor(
explicitReceiverKind: ExplicitReceiverKind,
scope: FirScope?,
dispatchReceiverValue: ReceiverValue? = null,
importedQualifierForStatic: FirExpression? = null,
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
objectsByName: Boolean = false
): Candidate {
@@ -56,10 +57,15 @@ class CandidateFactory private constructor(
val symbol = symbol.unwrapIntegerOperatorSymbolIfNeeded(callInfo)
val result = Candidate(
symbol, dispatchReceiverValue, givenExtensionReceiverOptions,
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
symbol,
dispatchReceiverValue,
givenExtensionReceiverOptions,
explicitReceiverKind,
context.inferenceComponents.constraintSystemFactory,
baseSystem,
callInfo,
scope,
importedQualifierForStatic,
isFromCompanionObjectTypeScope = when (explicitReceiverKind) {
ExplicitReceiverKind.EXTENSION_RECEIVER ->
givenExtensionReceiverOptions.singleOrNull().isCandidateFromCompanionObjectTypeScope()
@@ -540,7 +540,10 @@ internal object CheckVisibility : CheckerStage() {
sink.yieldDiagnostic(VisibilityError)
}
if (!visibilityChecker.isVisible(declaration, candidate.callInfo, dispatchReceiverValue = null)) {
if (!visibilityChecker.isVisible(
declaration, candidate.callInfo, dispatchReceiverValue = null, importedQualifierForStatic = null
)
) {
sink.yieldDiagnostic(VisibilityError)
}
}
@@ -13,6 +13,7 @@ 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
@@ -27,10 +28,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun FirVisibilityChecker.isVisible(
declaration: FirMemberDeclaration,
callInfo: CallInfo,
dispatchReceiverValue: ReceiverValue?
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?
): Boolean {
val staticQualifierForCallable = runIf(declaration is FirCallableDeclaration && declaration.isStatic) {
val explicitReceiver = callInfo.explicitReceiver ?: (dispatchReceiverValue as? ExpressionReceiverValue)?.explicitReceiver
val explicitReceiver = callInfo.explicitReceiver ?: importedQualifierForStatic
(explicitReceiver as? FirResolvedQualifier)?.symbol?.fir as? FirRegularClass
}
return isVisible(
@@ -49,19 +51,21 @@ fun FirVisibilityChecker.isVisible(
candidate: Candidate
): Boolean {
val callInfo = candidate.callInfo
val dispatchReceiverValue = candidate.dispatchReceiverValue
val importedQualifierForStatic = candidate.importedQualifierForStatic
if (!isVisible(declaration, callInfo, candidate.dispatchReceiverValue)) {
if (!isVisible(declaration, callInfo, dispatchReceiverValue, importedQualifierForStatic)) {
val dispatchReceiverWithoutSmartCastType =
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiverValue, candidate.callInfo.session) ?: return false
removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue, candidate.callInfo.session) ?: return false
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType, importedQualifierForStatic)) return false
candidate.dispatchReceiverValue = dispatchReceiverWithoutSmartCastType
}
val backingField = declaration.getBackingFieldIfApplicable()
if (backingField != null) {
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiverValue)
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, dispatchReceiverValue, importedQualifierForStatic)
}
return true
@@ -5,6 +5,7 @@
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
@@ -74,6 +75,7 @@ private class TowerScopeLevelProcessor(
override fun consumeCandidate(
symbol: FirBasedSymbol<*>,
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?,
givenExtensionReceiverOptions: List<ReceiverValue>,
scope: FirScope,
objectsByName: Boolean
@@ -85,6 +87,7 @@ private class TowerScopeLevelProcessor(
explicitReceiverKind,
scope,
dispatchReceiverValue,
importedQualifierForStatic,
givenExtensionReceiverOptions,
objectsByName
), candidateFactory.context
@@ -7,9 +7,12 @@ 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.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
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,6 +28,7 @@ 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;
@@ -53,6 +57,7 @@ abstract class TowerScopeLevel {
fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?,
givenExtensionReceiverOptions: List<ReceiverValue>,
scope: FirScope,
objectsByName: Boolean = false
@@ -132,7 +137,13 @@ class MemberScopeTowerLevel(
)
withSynthetic?.processScopeMembers { symbol ->
empty = false
output.consumeCandidate(symbol, dispatchReceiverValue, givenExtensionReceiverOptions = emptyList(), scope)
output.consumeCandidate(
symbol,
dispatchReceiverValue,
importedQualifierForStatic = null,
givenExtensionReceiverOptions = emptyList(),
scope
)
}
}
return if (empty) ProcessResult.SCOPE_EMPTY else ProcessResult.FOUND
@@ -158,7 +169,7 @@ class MemberScopeTowerLevel(
val candidates = mutableListOf<MemberWithBaseScope<T>>()
for (group in overridableGroups) {
val visibleCandidates = group.filter {
visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue)
visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue, importedQualifierForStatic = null)
}
val visibleCandidatesFromSmartcast = visibleCandidates.filter { candidatesMapping.getValue(it) }
@@ -192,12 +203,12 @@ class MemberScopeTowerLevel(
for ((candidate, scope) in candidatesWithScope) {
if (candidate.hasConsistentExtensionReceiver(givenExtensionReceiverOptions)) {
output.consumeCandidate(
candidate, dispatchReceiverValue,
candidate,
dispatchReceiverValue,
importedQualifierForStatic = null,
givenExtensionReceiverOptions,
scope
)
} else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, givenExtensionReceiverOptions, scope)
}
}
}
@@ -215,7 +226,6 @@ class MemberScopeTowerLevel(
processor = {
lookupCtx.recordCallableMemberLookup(it)
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
@Suppress("UNCHECKED_CAST")
consumer(it as FirFunctionSymbol<*>)
}
)
@@ -313,21 +323,27 @@ class ScopeTowerLevel(
fun areThereExtensionReceiverOptions(): Boolean = givenExtensionReceiverOptions.isNotEmpty()
private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? {
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)
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)
}
if (candidate !is FirBackingFieldSymbol) {
return null
@@ -381,13 +397,22 @@ class ScopeTowerLevel(
val receiverExpected = withHideMembersOnly || areThereExtensionReceiverOptions()
if (candidateReceiverTypeRef == null == receiverExpected) return
val dispatchReceiverValue = dispatchReceiverValue(candidate)
if (dispatchReceiverValue == null && shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)) {
val isStatic = candidate.fir.isStatic
val importedQualifierForStatic = runIf(isStatic) {
candidate.fir.importedQualifierForObjectOrStatic()
}
if (dispatchReceiverValue == null &&
importedQualifierForStatic == null &&
shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)
) {
return
}
val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol ?: candidate
val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol.takeIf { !isStatic } ?: candidate
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(
unwrappedCandidate as T, dispatchReceiverValue,
unwrappedCandidate as T,
dispatchReceiverValue,
importedQualifierForStatic,
givenExtensionReceiverOptions,
scope
)
@@ -433,7 +458,9 @@ class ScopeTowerLevel(
scope.processClassifiersByName(info.name) {
empty = false
processor.consumeCandidate(
it, dispatchReceiverValue = null,
it,
dispatchReceiverValue = null,
importedQualifierForStatic = null,
givenExtensionReceiverOptions = emptyList(),
scope = scope,
objectsByName = true