diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt index 9b6d1325d05..b767e33ba33 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirSingleRe import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider +import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeclarationStatusIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration import org.jetbrains.kotlin.fir.FirElementWithResolveState @@ -21,7 +22,11 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.StatusComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector +import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.Name @@ -83,7 +88,7 @@ private fun LLFirResolveTarget.resolveMode(): StatusResolveMode = when (this) { else -> StatusResolveMode.AllCallables } -private class LLStatusComputationSession : StatusComputationSession() { +private class LLStatusComputationSession(val useSiteSession: FirSession) : StatusComputationSession() { private var shouldCheckForActualization: Boolean = false inline fun withClass(regularClass: FirClass, transformer: (FirClass) -> Unit) { @@ -107,7 +112,7 @@ private class LLFirStatusTargetResolver( lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, - private val statusComputationSession: LLStatusComputationSession = LLStatusComputationSession(), + private val statusComputationSession: LLStatusComputationSession = LLStatusComputationSession(session), private val resolveMode: StatusResolveMode, ) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.STATUS, isJumpingPhase = false) { private val transformer = Transformer(session, scopeSession) @@ -236,6 +241,15 @@ private class LLFirStatusTargetResolver( return klass } + override fun superTypeToSymbols(typeRef: FirTypeRef): List> { + val type = typeRef.coneType + val originalClassifierSymbol = type.toSymbol(session) + val useSiteSymbol = type.toSymbol(computationSession.useSiteSession) + + // Resolve an 'expect' declaration before an 'actual' as it is like 'super' and 'sub' classes + return listOfNotNull(originalClassifierSymbol, useSiteSymbol?.takeIf { it != originalClassifierSymbol }) + } + override fun resolveClassForSuperType(regularClass: FirRegularClass): Boolean { // We cannot skip supertype resolution when there is a possibility // that some supertypes might need to be actualized in the current context @@ -248,11 +262,12 @@ private class LLFirStatusTargetResolver( } val target = regularClass.tryCollectDesignationWithFile()?.asResolveTarget() ?: return false + val targetSession = target.target.llFirSession val resolver = LLFirStatusTargetResolver( target, lockProvider, - session, - scopeSession, + targetSession, + targetSession.getScopeSession(), computationSession, resolveMode = resolveMode, ) diff --git a/analysis/low-level-api-fir/testData/lazyResolve/functions/actualOverride.txt b/analysis/low-level-api-fir/testData/lazyResolve/functions/actualOverride.txt index 2d00966f4cb..25e894d6a9e 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/functions/actualOverride.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/functions/actualOverride.txt @@ -270,10 +270,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt STATUS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -315,10 +315,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt EXPECT_ACTUAL_MATCHING: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -360,10 +360,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt CONTRACTS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -406,10 +406,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt IMPLICIT_TYPES_BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -452,10 +452,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt ANNOTATION_ARGUMENTS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -498,10 +498,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public open expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { diff --git a/analysis/low-level-api-fir/testData/lazyResolve/functions/transitiveSubstitutionFakeOverride.txt b/analysis/low-level-api-fir/testData/lazyResolve/functions/transitiveSubstitutionFakeOverride.txt index 5b9f988d737..c2744900ec0 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/functions/transitiveSubstitutionFakeOverride.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/functions/transitiveSubstitutionFakeOverride.txt @@ -282,10 +282,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt STATUS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -329,10 +329,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt EXPECT_ACTUAL_MATCHING: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -376,10 +376,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt CONTRACTS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -425,10 +425,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt IMPLICIT_TYPES_BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -474,10 +474,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt ANNOTATION_ARGUMENTS: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { @@ -523,10 +523,10 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] common.kt - public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| { - public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base| + public open expect [ResolvedTo(STATUS)] class Base<[ResolvedTo(STATUS)] T> : R|kotlin/Any| { + public expect [ResolvedTo(STATUS)] [ContainingClassKey=Base] constructor<[ResolvedTo(STATUS)] T>(): R|Base| - public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| + public final expect [ResolvedTo(STATUS)] fun existingMethodInBase([ResolvedTo(STATUS)] param: R|T|): R|kotlin/Unit| } public open [ResolvedTo(STATUS)] class Transitive : R|Base| { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index 825c1e8af60..7a8d1bdb867 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -328,26 +328,38 @@ abstract class AbstractFirStatusResolveTransformer( fun forceResolveStatusesOfSupertypes(regularClass: FirClass) { for (superTypeRef in regularClass.superTypeRefs) { - forceResolveStatusOfCorrespondingClass(superTypeRef) + for (classifierSymbol in superTypeToSymbols(superTypeRef)) { + forceResolveStatusOfCorrespondingClass(classifierSymbol) + } } } - private fun forceResolveStatusOfCorrespondingClass(typeRef: FirTypeRef) { - val superClassSymbol = typeRef.coneType.toSymbol(session) + /** + * @return symbols which should be resolved to [FirResolvePhase.STATUS] phase + */ + protected open fun superTypeToSymbols(typeRef: FirTypeRef): List> { + return listOfNotNull(typeRef.coneType.toSymbol(session)) + } + + private fun forceResolveStatusOfCorrespondingClass(superClassSymbol: FirClassifierSymbol<*>) { if (isTransformerForLocalDeclarations) { if (superClassSymbol is FirClassSymbol) { superClassSymbol.lazyResolveToPhaseWithCallableMembers(FirResolvePhase.STATUS) } else { - superClassSymbol?.lazyResolveToPhase(FirResolvePhase.STATUS) + superClassSymbol.lazyResolveToPhase(FirResolvePhase.STATUS) } } else { - superClassSymbol?.lazyResolveToPhase(FirResolvePhase.STATUS.previous) + superClassSymbol.lazyResolveToPhase(FirResolvePhase.STATUS.previous) } when (superClassSymbol) { is FirRegularClassSymbol -> forceResolveStatusesOfClass(superClassSymbol.fir) - is FirTypeAliasSymbol -> forceResolveStatusOfCorrespondingClass(superClassSymbol.fir.expandedTypeRef) - is FirTypeParameterSymbol, is FirAnonymousObjectSymbol, null -> {} + is FirTypeAliasSymbol -> { + for (classifierSymbol in superTypeToSymbols(superClassSymbol.fir.expandedTypeRef)) { + forceResolveStatusOfCorrespondingClass(classifierSymbol) + } + } + is FirTypeParameterSymbol, is FirAnonymousObjectSymbol -> {} } }