[LL FIR] LLFirSuperTypeTargetResolver: pass correct session during resolution

We should use the declaration-site session to have stable
resolution order. The same scheme is applicable during
regular lazy resolution calls.
Also, this means that we should process 'expect' classes
before 'actual' like it was for 'super' and 'sub' classes

^KT-63547
This commit is contained in:
Dmitrii Gridin
2023-12-21 01:13:43 +01:00
committed by Space Team
parent 960a59d49a
commit de44b7dc3b
3 changed files with 95 additions and 61 deletions
@@ -11,10 +11,13 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarg
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.session import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.session
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile 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.file.builder.LLFirLockProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isActual
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
@@ -26,6 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationStatus import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationStatus
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
import org.jetbrains.kotlin.fir.resolve.transformers.platformSupertypeUpdater import org.jetbrains.kotlin.fir.resolve.transformers.platformSupertypeUpdater
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -157,8 +161,10 @@ private class LLFirSuperTypeTargetResolver(
// 2. Resolve super declarations // 2. Resolve super declarations
val status = supertypeComputationSession.getSupertypesComputationStatus(declaration) val status = supertypeComputationSession.getSupertypesComputationStatus(declaration)
if (status is SupertypeComputationStatus.Computed) { if (status is SupertypeComputationStatus.Computed) {
for (computedType in status.supertypeRefs) { supertypeComputationSession.withClassLikeDeclaration(declaration) {
crawlSupertype(computedType.type) for (computedType in status.supertypeRefs) {
crawlSupertype(computedType.type, resolveTargetSession)
}
} }
} }
@@ -175,7 +181,7 @@ private class LLFirSuperTypeTargetResolver(
} }
private fun FirClassLikeDeclaration.asResolveTarget(): LLFirSingleResolveTarget? { private fun FirClassLikeDeclaration.asResolveTarget(): LLFirSingleResolveTarget? {
return takeIf { canHaveLoopInSupertypesHierarchy(it, resolveTargetSession) } return takeIf { supertypeComputationSession.canHaveLoopInSupertypesHierarchy(it) }
?.tryCollectDesignationWithFile() ?.tryCollectDesignationWithFile()
?.asResolveTarget() ?.asResolveTarget()
} }
@@ -184,7 +190,7 @@ private class LLFirSuperTypeTargetResolver(
LLFirSuperTypeTargetResolver( LLFirSuperTypeTargetResolver(
target = target, target = target,
lockProvider = lockProvider, lockProvider = lockProvider,
scopeSession = scopeSession, scopeSession = target.session.getScopeSession(),
supertypeComputationSession = supertypeComputationSession, supertypeComputationSession = supertypeComputationSession,
visitedElements = visitedElements, visitedElements = visitedElements,
).resolveDesignation() ).resolveDesignation()
@@ -196,21 +202,41 @@ private class LLFirSuperTypeTargetResolver(
* We want to apply resolved supertypes to as many designations as possible. * We want to apply resolved supertypes to as many designations as possible.
* So we crawl the resolved supertypes of visited designations to find more designations to collect. * So we crawl the resolved supertypes of visited designations to find more designations to collect.
*/ */
private fun crawlSupertype(type: ConeKotlinType) { private fun crawlSupertype(type: ConeKotlinType, declarationSiteSession: LLFirSession) {
val classLikeDeclaration = type.toSymbol(resolveTargetSession)?.fir // Resolve an 'expect' declaration before an 'actual' as it is like 'super' and 'sub' classes
for (session in listOf(declarationSiteSession, supertypeComputationSession.useSiteSession)) {
/**
* We can avoid deduplication here as the symbol will be checked with [visitedElements]
*/
type.toSymbol(session)?.let(::crawlSupertype)
}
if (type is ConeClassLikeType) {
// The `classLikeDeclaration` is not associated with a file, and thus there is no need to resolve it, but it may still point
// to declarations via its type arguments which need to be collected and have a containing file.
// For example, a `Function1` could point to a type alias.
type.typeArguments.forEach { it.type?.let { crawlSupertype(it, declarationSiteSession) } }
}
}
private fun crawlSupertype(symbol: FirClassifierSymbol<*>) {
val classLikeDeclaration = symbol.fir
if (classLikeDeclaration !is FirClassLikeDeclaration) return if (classLikeDeclaration !is FirClassLikeDeclaration) return
if (classLikeDeclaration in visitedElements) return if (classLikeDeclaration in visitedElements) return
if (classLikeDeclaration is FirJavaClass) { if (classLikeDeclaration is FirJavaClass) {
if (!canHaveLoopInSupertypesHierarchy(classLikeDeclaration, resolveTargetSession)) return if (!supertypeComputationSession.canHaveLoopInSupertypesHierarchy(classLikeDeclaration)) return
visitedElements += classLikeDeclaration visitedElements += classLikeDeclaration
val parentClass = classLikeDeclaration.outerClass(resolveTargetSession)
val session = classLikeDeclaration.llFirSession
val parentClass = classLikeDeclaration.outerClass(session)
if (parentClass != null) { if (parentClass != null) {
crawlSupertype(parentClass.defaultType()) crawlSupertype(parentClass.defaultType(), session)
} }
classLikeDeclaration.superTypeRefs.filterIsInstance<FirResolvedTypeRef>().forEach { classLikeDeclaration.superTypeRefs.filterIsInstance<FirResolvedTypeRef>().forEach {
crawlSupertype(it.type) crawlSupertype(it.type, session)
} }
return return
@@ -219,11 +245,6 @@ private class LLFirSuperTypeTargetResolver(
val resolveTarget = classLikeDeclaration.asResolveTarget() val resolveTarget = classLikeDeclaration.asResolveTarget()
if (resolveTarget != null) { if (resolveTarget != null) {
resolveToSupertypePhase(resolveTarget) resolveToSupertypePhase(resolveTarget)
} else if (type is ConeClassLikeType) {
// The `classLikeDeclaration` is not associated with a file, and thus there is no need to resolve it, but it may still point
// to declarations via its type arguments which need to be collected and have a containing file.
// For example, a `Function1` could point to a type alias.
type.typeArguments.forEach { it.type?.let(::crawlSupertype) }
} }
} }
@@ -232,26 +253,6 @@ private class LLFirSuperTypeTargetResolver(
} }
} }
/**
* We shouldn't skip Java source classes because they're marked as BODY_RESOLVE,
* but this doesn't give us knowledge about its participation in the calculation of supertypes.
* The contract here if a declaration is already resolved to FirResolvePhase.SUPER_TYPES or higher that this
* means that this class can't have loop with our class, because in this case this declaration will be present
* in the current supertypes resolve session
*/
private fun canHaveLoopInSupertypesHierarchy(
classLikeDeclaration: FirClassLikeDeclaration,
session: FirSession,
): Boolean = when {
classLikeDeclaration is FirJavaClass -> classLikeDeclaration.origin is FirDeclarationOrigin.Java.Source
classLikeDeclaration.origin !is FirDeclarationOrigin.Source -> false
classLikeDeclaration.resolvePhase < FirResolvePhase.SUPER_TYPES -> true
// We should still process resolved if it has loop in super type refs, because we can be part of this cycle
classLikeDeclaration is FirRegularClass && classLikeDeclaration.superTypeRefs.any(FirTypeRef::isLoopedSupertypeRef) -> true
classLikeDeclaration is FirTypeAlias && classLikeDeclaration.expandedTypeRef.isLoopedSupertypeRef -> true
else -> classLikeDeclaration.outerClass(session)?.let { canHaveLoopInSupertypesHierarchy(it, session) } == true
}
private fun FirClassLikeDeclaration.outerClass(session: FirSession): FirRegularClass? = symbol.classId.parentClassId?.let { parentClassId -> private fun FirClassLikeDeclaration.outerClass(session: FirSession): FirRegularClass? = symbol.classId.parentClassId?.let { parentClassId ->
session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir as? FirRegularClass session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir as? FirRegularClass
} }
@@ -263,7 +264,40 @@ private val FirTypeRef.isLoopedSupertypeRef: Boolean
return diagnostic is ConeSimpleDiagnostic && diagnostic.kind == DiagnosticKind.LoopInSupertype return diagnostic is ConeSimpleDiagnostic && diagnostic.kind == DiagnosticKind.LoopInSupertype
} }
private class LLFirSupertypeComputationSession(private val useSiteSession: FirSession) : SupertypeComputationSession() { private class LLFirSupertypeComputationSession(val useSiteSession: LLFirSession) : SupertypeComputationSession() {
private var shouldCheckForActualization: Boolean = false
inline fun withClassLikeDeclaration(classLikeDeclaration: FirClassLikeDeclaration, transformer: (FirClassLikeDeclaration) -> Unit) {
val oldValue = shouldCheckForActualization
if (classLikeDeclaration.isActual) {
shouldCheckForActualization = true
}
try {
transformer(classLikeDeclaration)
} finally {
shouldCheckForActualization = oldValue
}
}
/**
* We shouldn't skip Java source classes because they're marked as BODY_RESOLVE,
* but this doesn't give us knowledge about its participation in the calculation of supertypes.
* The contract here if a declaration is already resolved to FirResolvePhase.SUPER_TYPES or higher that this
* means that this class can't have loop with our class, because in this case this declaration will be present
* in the current supertypes resolve session
*/
fun canHaveLoopInSupertypesHierarchy(classLikeDeclaration: FirClassLikeDeclaration): Boolean = when {
classLikeDeclaration is FirJavaClass -> classLikeDeclaration.origin is FirDeclarationOrigin.Java.Source
classLikeDeclaration.origin !is FirDeclarationOrigin.Source -> false
shouldCheckForActualization -> true
classLikeDeclaration.resolvePhase < FirResolvePhase.SUPER_TYPES -> true
// We should still process resolved if it has loop in super type refs, because we can be part of this cycle
classLikeDeclaration is FirRegularClass && classLikeDeclaration.superTypeRefs.any(FirTypeRef::isLoopedSupertypeRef) -> true
classLikeDeclaration is FirTypeAlias && classLikeDeclaration.expandedTypeRef.isLoopedSupertypeRef -> true
else -> classLikeDeclaration.outerClass(classLikeDeclaration.llFirSession)?.let(::canHaveLoopInSupertypesHierarchy) == true
}
/** /**
* These collections exist to reuse a collection for each search to avoid repeated memory allocation. * These collections exist to reuse a collection for each search to avoid repeated memory allocation.
* Can be replaced with a new collection on each invocation of [findLoopFor] * Can be replaced with a new collection on each invocation of [findLoopFor]
@@ -302,7 +336,7 @@ private class LLFirSupertypeComputationSession(private val useSiteSession: FirSe
} }
override fun isAlreadyResolved(classLikeDeclaration: FirClassLikeDeclaration): Boolean { override fun isAlreadyResolved(classLikeDeclaration: FirClassLikeDeclaration): Boolean {
return !canHaveLoopInSupertypesHierarchy(classLikeDeclaration, useSiteSession) return !canHaveLoopInSupertypesHierarchy(classLikeDeclaration)
} }
/** /**
@@ -1,7 +1,7 @@
RAW_FIR: RAW_FIR:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -45,8 +45,8 @@ FILE: [ResolvedTo(RAW_FIR)] jvm.kt
IMPORTS: IMPORTS:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -90,8 +90,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
COMPILER_REQUIRED_ANNOTATIONS: COMPILER_REQUIRED_ANNOTATIONS:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -135,8 +135,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
COMPANION_GENERATION: COMPANION_GENERATION:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -180,8 +180,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
SUPER_TYPES: SUPER_TYPES:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -225,8 +225,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
TYPES: TYPES:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? open expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -1,7 +1,7 @@
RAW_FIR: RAW_FIR:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -47,8 +47,8 @@ FILE: [ResolvedTo(RAW_FIR)] jvm.kt
IMPORTS: IMPORTS:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -94,8 +94,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
COMPILER_REQUIRED_ANNOTATIONS: COMPILER_REQUIRED_ANNOTATIONS:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -141,8 +141,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
COMPANION_GENERATION: COMPANION_GENERATION:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -188,8 +188,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
SUPER_TYPES: SUPER_TYPES:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|
@@ -235,8 +235,8 @@ FILE: [ResolvedTo(IMPORTS)] jvm.kt
TYPES: TYPES:
FILE: [ResolvedTo(IMPORTS)] common.kt FILE: [ResolvedTo(IMPORTS)] common.kt
public? open expect [ResolvedTo(RAW_FIR)] class Base<[ResolvedTo(RAW_FIR)] T> : R|kotlin/Any| { public? open expect [ResolvedTo(SUPER_TYPES)] class Base<[ResolvedTo(SUPER_TYPES)] T> : R|kotlin/Any| {
public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(RAW_FIR)] T>(): R|Base<T>| public? expect [ResolvedTo(RAW_FIR)] [ContainingClassKey=Base] constructor<[ResolvedTo(SUPER_TYPES)] T>(): R|Base<T>|
public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit| public? final? expect [ResolvedTo(RAW_FIR)] fun existingMethodInBase([ResolvedTo(RAW_FIR)] param: T): R|kotlin/Unit|