[FIR] fix resolve contract violation from scopes

We cannot call lazy resolve to STATUS phase from scopes as scopes may be accessed on a STATUS phase or earlier

^KT-54890
^KTIJ-23587 fixed
This commit is contained in:
Ilya Kirillov
2022-12-28 09:59:12 +01:00
committed by teamcity
parent 0d1e7e83b5
commit 1bbcae5ed2
311 changed files with 108 additions and 347 deletions
@@ -28,14 +28,21 @@ import org.jetbrains.kotlin.name.ClassId
fun FirSmartCastExpression.smartcastScope(
useSiteSession: FirSession,
scopeSession: ScopeSession
scopeSession: ScopeSession,
requiredPhase: FirResolvePhase? = null,
): FirTypeScope? {
val smartcastType = smartcastTypeWithoutNullableNothing?.coneType ?: smartcastType.coneType
val smartcastScope = smartcastType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
val smartcastScope = smartcastType.scope(
useSiteSession,
scopeSession,
FakeOverrideTypeCalculator.DoNothing,
requiredPhase = FirResolvePhase.STATUS
)
if (isStable) {
return smartcastScope
}
val originalScope = originalExpression.typeRef.coneType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
val originalScope = originalExpression.typeRef.coneType
.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase)
?: return smartcastScope
if (smartcastScope == null) {
@@ -55,14 +62,15 @@ fun ConeClassLikeType.delegatingConstructorScope(
fun ConeKotlinType.scope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
fakeOverrideTypeCalculator: FakeOverrideTypeCalculator
fakeOverrideTypeCalculator: FakeOverrideTypeCalculator,
requiredPhase: FirResolvePhase?,
): FirTypeScope? {
val scope = scope(useSiteSession, scopeSession, FirResolvePhase.DECLARATIONS) ?: return null
val scope = scope(useSiteSession, scopeSession, requiredPhase) ?: return null
if (fakeOverrideTypeCalculator == FakeOverrideTypeCalculator.DoNothing) return scope
return FirScopeWithFakeOverrideTypeCalculator(scope, fakeOverrideTypeCalculator)
}
private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession, requiredPhase: FirResolvePhase): FirTypeScope? {
private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession, requiredPhase: FirResolvePhase?): FirTypeScope? {
return when (this) {
is ConeErrorType -> null
is ConeClassLikeType -> classScope(useSiteSession, scopeSession, requiredPhase, lookupTag)
@@ -99,13 +107,15 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
private fun ConeClassLikeType.classScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
requiredPhase: FirResolvePhase,
requiredPhase: FirResolvePhase?,
memberOwnerLookupTag: ConeClassLikeLookupTag
): FirTypeScope? {
val fullyExpandedType = fullyExpandedType(useSiteSession)
val fir = fullyExpandedType.lookupTag.toSymbol(useSiteSession)?.fir as? FirClass ?: return null
fir.symbol.lazyResolveToPhase(requiredPhase)
if (requiredPhase != null) {
fir.symbol.lazyResolveToPhase(requiredPhase)
}
val substitutor = when {
attributes.contains(CompilerConeAttributes.RawType) -> ConeRawScopeSubstitutor(useSiteSession)
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.copyWithNewSourceKind
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildSmartCastExpression
@@ -41,7 +42,7 @@ interface ReceiverValue : Receiver {
val receiverExpression: FirExpression
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
}
// TODO: should inherit just Receiver, not ReceiverValue
@@ -70,9 +71,9 @@ open class ExpressionReceiverValue(
receiverExpr = receiverExpr.arguments.firstOrNull()
}
if (receiverExpr is FirSmartCastExpression) {
return receiverExpr.smartcastScope(useSiteSession, scopeSession)
return receiverExpr.smartcastScope(useSiteSession, scopeSession, requiredPhase = FirResolvePhase.STATUS)
}
return type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
return type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
}
}
@@ -91,7 +92,8 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
val originalType: ConeKotlinType = type
var implicitScope: FirTypeScope? = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
var implicitScope: FirTypeScope? =
type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
private set
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? = implicitScope
@@ -132,7 +134,8 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
typeRef = smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
}
}
implicitScope = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
implicitScope =
type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
}
abstract fun createSnapshot(): ImplicitReceiverValue<S>
@@ -8,16 +8,14 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.name.ClassId
fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSession: ScopeSession): FirContainingNamesAwareScope? {
val klass = toSymbol(session)?.fir as? FirRegularClass ?: return null
@@ -29,7 +27,12 @@ fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSe
*/
@TestOnly
fun debugCollectOverrides(symbol: FirCallableSymbol<*>, session: FirSession, scopeSession: ScopeSession): Map<Any, Any> {
val scope = symbol.dispatchReceiverType?.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing) ?: return emptyMap()
val scope = symbol.dispatchReceiverType?.scope(
session,
scopeSession,
FakeOverrideTypeCalculator.DoNothing,
requiredPhase = FirResolvePhase.STATUS
) ?: return emptyMap()
return debugCollectOverrides(symbol, scope)
}
@@ -116,6 +116,7 @@ class FirClassSubstitutionScope(
fun createSubstitutionOverrideFunction(original: FirNamedFunctionSymbol): FirNamedFunctionSymbol {
if (substitutor == ConeSubstitutor.Empty) return original
original.lazyResolveToPhase(FirResolvePhase.TYPES)
val member = original.fir
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
@@ -175,6 +176,7 @@ class FirClassSubstitutionScope(
fun createSubstitutionOverrideConstructor(original: FirConstructorSymbol): FirConstructorSymbol {
if (substitutor == ConeSubstitutor.Empty) return original
original.lazyResolveToPhase(FirResolvePhase.TYPES)
val constructor = original.fir
val symbolForOverride = FirConstructorSymbol(original.callableId)
@@ -221,6 +223,7 @@ class FirClassSubstitutionScope(
fun createSubstitutionOverrideProperty(original: FirPropertySymbol): FirPropertySymbol {
if (substitutor == ConeSubstitutor.Empty) return original
original.lazyResolveToPhase(FirResolvePhase.TYPES)
val member = original.fir
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
@@ -279,7 +282,6 @@ class FirClassSubstitutionScope(
)
private fun createSubstitutedData(member: FirCallableDeclaration, symbolForOverride: FirBasedSymbol<*>): SubstitutedData {
member.lazyResolveToPhase(FirResolvePhase.TYPES)
val (newTypeParameters, substitutor) = FirFakeOverrideGenerator.createNewTypeParametersAndSubstitutor(
session,
member as FirTypeParameterRefsOwner,
@@ -293,7 +295,6 @@ class FirClassSubstitutionScope(
val newDispatchReceiverType = dispatchReceiverTypeForSubstitutedMembers.substitute(substitutor)
member.lazyResolveToPhase(FirResolvePhase.STATUS)
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, member.symbol) }
val newReturnType = returnType?.substitute(substitutor)
@@ -309,10 +310,10 @@ class FirClassSubstitutionScope(
fun createSubstitutionOverrideField(original: FirFieldSymbol): FirFieldSymbol {
if (substitutor == ConeSubstitutor.Empty) return original
original.lazyResolveToPhase(FirResolvePhase.TYPES)
val member = original.fir
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
member.symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
// TODO: do we have fields with implicit type?
val newReturnType = returnType?.substitute() ?: return original
@@ -322,10 +323,10 @@ class FirClassSubstitutionScope(
fun createSubstitutionOverrideSyntheticProperty(original: FirSyntheticPropertySymbol): FirSyntheticPropertySymbol {
if (substitutor == ConeSubstitutor.Empty) return original
original.lazyResolveToPhase(FirResolvePhase.TYPES)
val member = original.fir as FirSyntheticProperty
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
member.symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, original) }
val newReturnType = returnType?.substitute()
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeFlexibleType
@@ -49,8 +48,8 @@ class FirDelegatedMemberScope(
}
private fun buildScope(delegateField: FirField): FirTypeScope? {
delegateField.lazyResolveToPhase(FirResolvePhase.TYPES)
return delegateField.returnTypeRef.coneType.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
return delegateField.returnTypeRef.coneType
.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = null)
}
private fun collectFunctionsFromSpecificField(
@@ -18,7 +18,9 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirOperationNameConventions
import org.jetbrains.kotlin.fir.moduleData
@@ -59,7 +61,7 @@ class FirDynamicScope @FirDynamicScopeConstructor constructor(
override fun getClassifierNames(): Set<Name> = emptySet()
private val anyTypeScope by lazy {
session.builtinTypes.anyType.type.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
session.builtinTypes.anyType.type.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = null)
}
override fun processFunctionsByName(
@@ -35,7 +35,8 @@ class FirIntegerConstantOperatorScope(
true -> session.builtinTypes.uIntType
false -> session.builtinTypes.intType
}.type
baseType.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing) ?: error("Scope for $baseType not found")
baseType.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = null)
?: error("Scope for $baseType not found")
}
private val mappedFunctions = mutableMapOf<Name, FirNamedFunctionSymbol>()
@@ -192,7 +192,7 @@ fun ConeKotlinType.findContributedInvokeSymbol(
} else {
FakeOverrideTypeCalculator.DoNothing
}
val scope = scope(session, scopeSession, fakeOverrideTypeCalculator) ?: return null
val scope = scope(session, scopeSession, fakeOverrideTypeCalculator, requiredPhase = null) ?: return null
var declaredInvoke: FirNamedFunctionSymbol? = null
scope.processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
if (functionSymbol.fir.valueParameters.size == baseInvokeSymbol.fir.valueParameters.size) {