[FE] Fix 'containingClassForStaticMemberAttr' for fake overrides (KTIJ-22808)

This commit is contained in:
Yan Zhulanow
2022-10-24 15:35:38 +09:00
committed by Space Team
parent 2e9f9f987b
commit fe69b21aed
19 changed files with 176 additions and 84 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculat
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
import org.jetbrains.kotlin.fir.scopes.impl.dynamicMembersStorage
import org.jetbrains.kotlin.fir.scopes.impl.getOrBuildScopeForIntegerConstantOperatorType
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -43,6 +44,14 @@ fun FirSmartCastExpression.smartcastScope(
return FirUnstableSmartcastTypeScope(smartcastScope, originalScope)
}
fun ConeClassLikeType.delegatingConstructorScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
derivedClassLookupTag: ConeClassLikeLookupTag?
): FirTypeScope? {
return classScope(useSiteSession, scopeSession, FirResolvePhase.DECLARATIONS, derivedClassLookupTag)
}
fun ConeKotlinType.scope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
@@ -56,23 +65,7 @@ fun ConeKotlinType.scope(
private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession, requiredPhase: FirResolvePhase): FirTypeScope? {
return when (this) {
is ConeErrorType -> null
is ConeClassLikeType -> {
val fullyExpandedType = fullyExpandedType(useSiteSession)
val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
fir.symbol.lazyResolveToPhase(requiredPhase)
val substitutor = when {
attributes.contains(CompilerConeAttributes.RawType) -> ConeRawScopeSubstitutor(useSiteSession)
else -> substitutorByMap(
createSubstitution(fir.typeParameters, fullyExpandedType, useSiteSession),
useSiteSession,
)
}
fir.scopeForClass(substitutor, useSiteSession, scopeSession)
}
is ConeClassLikeType -> classScope(useSiteSession, scopeSession, requiredPhase, derivedClassLookupTag = null)
is ConeTypeParameterType -> {
val symbol = lookupTag.symbol
scopeSession.getOrBuild(symbol, TYPE_PARAMETER_SCOPE_KEY) {
@@ -103,6 +96,28 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
}
}
private fun ConeClassLikeType.classScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
requiredPhase: FirResolvePhase,
derivedClassLookupTag: ConeClassLikeLookupTag?
): FirTypeScope? {
val fullyExpandedType = fullyExpandedType(useSiteSession)
val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
fir.symbol.lazyResolveToPhase(requiredPhase)
val substitutor = when {
attributes.contains(CompilerConeAttributes.RawType) -> ConeRawScopeSubstitutor(useSiteSession)
else -> substitutorByMap(
createSubstitution(fir.typeParameters, fullyExpandedType, useSiteSession),
useSiteSession,
)
}
return fir.scopeForClass(substitutor, useSiteSession, scopeSession, derivedClassLookupTag)
}
private fun ConeClassLikeType.obtainFirOfClass(useSiteSession: FirSession, requiredPhase: FirResolvePhase): FirClass? {
val fullyExpandedType = fullyExpandedType(useSiteSession)
val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
@@ -107,19 +107,21 @@ fun FirClassSymbol<*>.unsubstitutedScope(
fun FirClass.scopeForClass(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession
scopeSession: ScopeSession,
derivedClassLookupTag: ConeClassLikeLookupTag?
): FirTypeScope = scopeForClassImpl(
substitutor, useSiteSession, scopeSession,
skipPrivateMembers = false,
classFirDispatchReceiver = this,
// TODO: why it's always false?
isFromExpectClass = false
isFromExpectClass = false,
derivedClassLookupTag = derivedClassLookupTag
)
fun ConeKotlinType.scopeForSupertype(
useSiteSession: FirSession,
scopeSession: ScopeSession,
subClass: FirClass,
derivedClass: FirClass,
): FirTypeScope? {
if (this !is ConeClassLikeType) return null
if (this is ConeErrorType) return null
@@ -136,8 +138,9 @@ fun ConeKotlinType.scopeForSupertype(
useSiteSession,
scopeSession,
skipPrivateMembers = true,
classFirDispatchReceiver = subClass,
isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true
classFirDispatchReceiver = derivedClass,
isFromExpectClass = (derivedClass as? FirRegularClass)?.isExpect == true,
derivedClassLookupTag = derivedClass.symbol.toLookupTag()
)
}
@@ -153,7 +156,8 @@ private fun FirClass.scopeForClassImpl(
scopeSession: ScopeSession,
skipPrivateMembers: Boolean,
classFirDispatchReceiver: FirClass,
isFromExpectClass: Boolean
isFromExpectClass: Boolean,
derivedClassLookupTag: ConeClassLikeLookupTag?
): FirTypeScope {
val basicScope = unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator = false)
if (substitutor == ConeSubstitutor.Empty) return basicScope
@@ -168,7 +172,8 @@ private fun FirClass.scopeForClassImpl(
key, substitutor,
substitutor.substituteOrSelf(classFirDispatchReceiver.defaultType()).lowerBoundIfFlexible() as ConeClassLikeType,
skipPrivateMembers,
makeExpect = isFromExpectClass
makeExpect = isFromExpectClass,
derivedClassLookupTag ?: classFirDispatchReceiver.symbol.toLookupTag()
)
}
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.chain
import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
@@ -34,7 +35,8 @@ class FirClassSubstitutionScope(
private val substitutor: ConeSubstitutor,
private val dispatchReceiverTypeForSubstitutedMembers: ConeClassLikeType,
private val skipPrivateMembers: Boolean,
private val makeExpect: Boolean = false
private val makeExpect: Boolean = false,
private val derivedClassLookupTag: ConeClassLikeLookupTag
) : FirTypeScope() {
private val substitutionOverrideCache = session.substitutionOverrideStorage.substitutionOverrideCacheByScope.getValue(key, null)
@@ -142,6 +144,7 @@ class FirClassSubstitutionScope(
session,
symbolForOverride,
member,
derivedClassLookupTag = derivedClassLookupTag,
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
isExpect = makeExpect,
)
@@ -158,6 +161,7 @@ class FirClassSubstitutionScope(
session,
symbolForOverride,
member,
derivedClassLookupTag,
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
newReceiverType,
newContextReceiverTypes,
@@ -202,6 +206,7 @@ class FirClassSubstitutionScope(
symbolForOverride,
session,
constructor,
derivedClassLookupTag,
FirDeclarationOrigin.SubstitutionOverride,
newDispatchReceiverType,
// Constructors' return types are expected to be non-flexible (i.e., non raw)
@@ -240,6 +245,7 @@ class FirClassSubstitutionScope(
session,
symbolForOverride,
member,
derivedClassLookupTag = derivedClassLookupTag,
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
isExpect = makeExpect,
)
@@ -252,6 +258,7 @@ class FirClassSubstitutionScope(
session,
symbolForOverride,
member,
derivedClassLookupTag,
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
newReceiverType,
newContextReceiverTypes,
@@ -310,9 +317,7 @@ class FirClassSubstitutionScope(
// TODO: do we have fields with implicit type?
val newReturnType = returnType?.substitute() ?: return original
return FirFakeOverrideGenerator.createSubstitutionOverrideField(
session, member, original, newReturnType, newOwnerClassId
)
return FirFakeOverrideGenerator.createSubstitutionOverrideField(session, member, derivedClassLookupTag, newReturnType)
}
fun createSubstitutionOverrideSyntheticProperty(original: FirSyntheticPropertySymbol): FirSyntheticPropertySymbol {
@@ -347,6 +352,7 @@ class FirClassSubstitutionScope(
return FirFakeOverrideGenerator.createSubstitutionOverrideSyntheticProperty(
session,
member,
derivedClassLookupTag,
original,
substitutor.substituteOrSelf(dispatchReceiverTypeForSubstitutedMembers) as ConeSimpleKotlinType?,
newContextReceiverTypes,
@@ -92,6 +92,7 @@ class FirDelegatedMemberScope(
functionSymbol.callableId,
),
original,
derivedClassLookupTag = null,
session,
FirDeclarationOrigin.Delegated,
newDispatchReceiverType = dispatchReceiverType,
@@ -161,6 +162,7 @@ class FirDelegatedMemberScope(
propertySymbol.callableId
),
original,
derivedClassLookupTag = null,
session,
FirDeclarationOrigin.Delegated,
newModality = Modality.OPEN,
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution
import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -36,6 +37,7 @@ object FirFakeOverrideGenerator {
session: FirSession,
symbolForSubstitutionOverride: FirNamedFunctionSymbol,
baseFunction: FirSimpleFunction,
derivedClassLookupTag: ConeClassLikeLookupTag?,
newDispatchReceiverType: ConeSimpleKotlinType?,
newReceiverType: ConeKotlinType? = null,
newContextReceiverTypes: List<ConeKotlinType?>? = null,
@@ -46,8 +48,8 @@ object FirFakeOverrideGenerator {
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirNamedFunctionSymbol {
createSubstitutionOverrideFunction(
symbolForSubstitutionOverride, session, baseFunction, newDispatchReceiverType, newReceiverType, newContextReceiverTypes,
newReturnType, newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution
symbolForSubstitutionOverride, session, baseFunction, derivedClassLookupTag, newDispatchReceiverType, newReceiverType,
newContextReceiverTypes, newReturnType, newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution
)
return symbolForSubstitutionOverride
}
@@ -64,6 +66,7 @@ object FirFakeOverrideGenerator {
fakeOverrideSymbol: FirNamedFunctionSymbol,
session: FirSession,
baseFunction: FirSimpleFunction,
derivedClassLookupTag: ConeClassLikeLookupTag?,
newDispatchReceiverType: ConeSimpleKotlinType?,
newReceiverType: ConeKotlinType?,
newContextReceiverTypes: List<ConeKotlinType?>?,
@@ -78,6 +81,7 @@ object FirFakeOverrideGenerator {
return createCopyForFirFunction(
fakeOverrideSymbol,
baseFunction,
derivedClassLookupTag = derivedClassLookupTag,
session,
FirDeclarationOrigin.SubstitutionOverride,
isExpect,
@@ -90,15 +94,13 @@ object FirFakeOverrideGenerator {
fakeOverrideSubstitution = fakeOverrideSubstitution
).apply {
originalForSubstitutionOverrideAttr = baseFunction
if (isStatic) {
containingClassForStaticMemberAttr = (newDispatchReceiverType as? ConeClassLikeType)?.lookupTag
}
}
}
fun createCopyForFirFunction(
newSymbol: FirNamedFunctionSymbol,
baseFunction: FirSimpleFunction,
derivedClassLookupTag: ConeClassLikeLookupTag?,
session: FirSession,
origin: FirDeclarationOrigin,
isExpect: Boolean = baseFunction.isExpect,
@@ -128,6 +130,8 @@ object FirFakeOverrideGenerator {
newReceiverType, newContextReceiverTypes, newReturnType, fakeOverrideSubstitution, newSymbol
).filterIsInstance<FirTypeParameter>()
deprecationsProvider = baseFunction.deprecationsProvider
}.apply {
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseFunction) }
}
}
@@ -135,6 +139,7 @@ object FirFakeOverrideGenerator {
fakeOverrideSymbol: FirConstructorSymbol,
session: FirSession,
baseConstructor: FirConstructor,
derivedClassLookupTag: ConeClassLikeLookupTag?,
origin: FirDeclarationOrigin,
newDispatchReceiverType: ConeSimpleKotlinType?,
newReturnType: ConeKotlinType?,
@@ -179,6 +184,7 @@ object FirFakeOverrideGenerator {
deprecationsProvider = baseConstructor.deprecationsProvider
}.apply {
originalForSubstitutionOverrideAttr = baseConstructor
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseConstructor) }
}
}
@@ -303,6 +309,7 @@ object FirFakeOverrideGenerator {
session: FirSession,
symbolForSubstitutionOverride: FirPropertySymbol,
baseProperty: FirProperty,
derivedClassLookupTag: ConeClassLikeLookupTag,
newDispatchReceiverType: ConeSimpleKotlinType?,
newReceiverType: ConeKotlinType? = null,
newContextReceiverTypes: List<ConeKotlinType?>? = null,
@@ -312,14 +319,11 @@ object FirFakeOverrideGenerator {
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirPropertySymbol {
createCopyForFirProperty(
symbolForSubstitutionOverride, baseProperty, session, FirDeclarationOrigin.SubstitutionOverride, isExpect,
newDispatchReceiverType, newTypeParameters, newReceiverType, newContextReceiverTypes, newReturnType,
symbolForSubstitutionOverride, baseProperty, derivedClassLookupTag, session, FirDeclarationOrigin.SubstitutionOverride,
isExpect, newDispatchReceiverType, newTypeParameters, newReceiverType, newContextReceiverTypes, newReturnType,
fakeOverrideSubstitution = fakeOverrideSubstitution
).apply {
originalForSubstitutionOverrideAttr = baseProperty
if (isStatic) {
containingClassForStaticMemberAttr = (newDispatchReceiverType as? ConeClassLikeType)?.lookupTag
}
}
return symbolForSubstitutionOverride
}
@@ -335,6 +339,7 @@ object FirFakeOverrideGenerator {
fun createCopyForFirProperty(
newSymbol: FirPropertySymbol,
baseProperty: FirProperty,
derivedClassLookupTag: ConeClassLikeLookupTag?,
session: FirSession,
origin: FirDeclarationOrigin,
isExpect: Boolean = baseProperty.isExpect,
@@ -370,6 +375,8 @@ object FirFakeOverrideGenerator {
fakeOverrideSubstitution
)
deprecationsProvider = baseProperty.deprecationsProvider
}.apply {
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) }
}
}
@@ -485,13 +492,10 @@ object FirFakeOverrideGenerator {
fun createSubstitutionOverrideField(
session: FirSession,
baseField: FirField,
baseSymbol: FirFieldSymbol,
newReturnType: ConeKotlinType?,
derivedClassId: ClassId?
derivedClassLookupTag: ConeClassLikeLookupTag,
newReturnType: ConeKotlinType?
): FirFieldSymbol {
val symbol = FirFieldSymbol(
CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseField.name)
)
val symbol = FirFieldSymbol(CallableId(derivedClassLookupTag.classId, baseField.name))
buildField {
moduleData = session.moduleData
this.symbol = symbol
@@ -509,9 +513,7 @@ object FirFakeOverrideGenerator {
dispatchReceiverType = baseField.dispatchReceiverType
}.apply {
originalForSubstitutionOverrideAttr = baseField
if (isStatic && derivedClassId != null) {
containingClassForStaticMemberAttr = ConeClassLikeLookupTagImpl(derivedClassId)
}
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) }
}
return symbol
}
@@ -519,6 +521,7 @@ object FirFakeOverrideGenerator {
fun createSubstitutionOverrideSyntheticProperty(
session: FirSession,
baseProperty: FirSyntheticProperty,
derivedClassLookupTag: ConeClassLikeLookupTag,
baseSymbol: FirSyntheticPropertySymbol,
newDispatchReceiverType: ConeSimpleKotlinType?,
newContextReceiverTypes: List<ConeKotlinType?>?,
@@ -532,6 +535,7 @@ object FirFakeOverrideGenerator {
getterSymbol,
session,
baseProperty.getter.delegate,
derivedClassLookupTag,
newDispatchReceiverType,
newReceiverType = null,
newContextReceiverTypes,
@@ -546,6 +550,7 @@ object FirFakeOverrideGenerator {
setterSymbol,
session,
baseSetter.delegate,
derivedClassLookupTag,
newDispatchReceiverType,
newReceiverType = null,
newContextReceiverTypes,
@@ -562,6 +567,8 @@ object FirFakeOverrideGenerator {
delegateSetter = setter
status = baseProperty.status
deprecationsProvider = getDeprecationsProviderFromAccessors(getter, setter, session.firCachesFactory)
}.apply {
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseProperty) }
}.symbol
}
@@ -620,6 +627,12 @@ object FirFakeOverrideGenerator {
)
}
private fun shouldOverrideSetContainingClass(baseDeclaration: FirCallableDeclaration): Boolean {
return baseDeclaration is FirConstructor
|| baseDeclaration.isStatic
|| baseDeclaration.containingClassForStaticMemberAttr != null
}
private sealed class Maybe<out A> {
class Value<out A>(val value: A) : Maybe<A>()
object Nothing : Maybe<kotlin.Nothing>()
@@ -361,7 +361,9 @@ class FirTypeIntersectionScopeContext(
)
val newSymbol = FirIntersectionOverrideFunctionSymbol(callableId, overrides)
FirFakeOverrideGenerator.createCopyForFirFunction(
newSymbol, keyFir, session, FirDeclarationOrigin.IntersectionOverride, keyFir.isExpect,
newSymbol, keyFir,
derivedClassLookupTag = null,
session, FirDeclarationOrigin.IntersectionOverride, keyFir.isExpect,
newModality = newModality,
newVisibility = newVisibility,
newDispatchReceiverType = dispatchReceiverType,
@@ -386,7 +388,8 @@ class FirTypeIntersectionScopeContext(
)
val newSymbol = FirIntersectionOverridePropertySymbol(callableId, overrides)
FirFakeOverrideGenerator.createCopyForFirProperty(
newSymbol, keyFir, session, FirDeclarationOrigin.IntersectionOverride,
newSymbol, keyFir, derivedClassLookupTag = null, session,
FirDeclarationOrigin.IntersectionOverride,
newModality = newModality,
newVisibility = newVisibility,
newDispatchReceiverType = dispatchReceiverType,