[LL FIR] rewrite LLFirSuperTypeTargetResolver
The previous implementation had issues with locks, publication and performance Also, this change fixed a problem with mixed cycle inheritance ^KT-56550 ^KTIJ-25430 Fixed ^KTIJ-23520 Fixed ^KT-57623 Fixed ^KTIJ-25372 Fixed ^KT-58357 Fixed
This commit is contained in:
committed by
Space Team
parent
09d17d88d7
commit
c2b09d3b1e
@@ -30,11 +30,13 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.resolveSupertypesInTheAir
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.*
|
||||
@@ -113,7 +115,7 @@ class FirJavaElementFinder(
|
||||
|
||||
val superTypeRefs = when {
|
||||
firClass.superTypeRefs.all { it is FirResolvedTypeRef } -> firClass.superTypeRefs
|
||||
else -> firClass.resolveSupertypesInTheAir(session)
|
||||
else -> firClass.resolveSupertypesOnAir(session)
|
||||
}
|
||||
|
||||
stub.addSupertypesReferencesLists(firClass, superTypeRefs, session)
|
||||
@@ -127,6 +129,13 @@ class FirJavaElementFinder(
|
||||
|
||||
}
|
||||
|
||||
private fun FirRegularClass.resolveSupertypesOnAir(session: FirSession): List<FirTypeRef> {
|
||||
val visitor = FirSupertypeResolverVisitor(session, SupertypeComputationSession(), ScopeSession())
|
||||
return visitor.withFile(session.firProvider.getFirClassifierContainerFile(this.symbol)) {
|
||||
visitor.resolveSpecificClassLikeSupertypes(this, superTypeRefs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirSession.collectAllDependentSourceSessions(): List<FirSession> {
|
||||
val result = mutableListOf<FirSession>()
|
||||
collectAllDependentSourceSessionsTo(result)
|
||||
|
||||
+131
-89
@@ -50,11 +50,11 @@ class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSess
|
||||
override val transformer = FirSupertypeResolverTransformer(session, scopeSession)
|
||||
}
|
||||
|
||||
open class FirSupertypeResolverTransformer(
|
||||
final override val session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
class FirSupertypeResolverTransformer(
|
||||
override val session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : FirAbstractPhaseTransformer<Any?>(FirResolvePhase.SUPER_TYPES) {
|
||||
protected val supertypeComputationSession = SupertypeComputationSession()
|
||||
private val supertypeComputationSession = SupertypeComputationSession()
|
||||
|
||||
private val supertypeResolverVisitor = FirSupertypeResolverVisitor(session, supertypeComputationSession, scopeSession)
|
||||
private val applySupertypesTransformer = FirApplySupertypesTransformer(supertypeComputationSession, session, scopeSession)
|
||||
@@ -97,18 +97,18 @@ fun <F : FirClassLikeDeclaration> F.runSupertypeResolvePhaseForLocalClass(
|
||||
return this.transform<F, Nothing?>(applySupertypesTransformer, null)
|
||||
}
|
||||
|
||||
open class FirApplySupertypesTransformer(
|
||||
private class FirApplySupertypesTransformer(
|
||||
private val supertypeComputationSession: SupertypeComputationSession,
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession
|
||||
private val scopeSession: ScopeSession,
|
||||
) : FirDefaultTransformer<Any?>() {
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
||||
return element
|
||||
}
|
||||
|
||||
protected open fun transformDeclarationContent(declaration: FirDeclaration, data: Any?): FirDeclaration {
|
||||
return declaration.transformChildren(this, null) as FirDeclaration
|
||||
private fun transformDeclarationContent(declaration: FirDeclaration, data: Any?): FirDeclaration {
|
||||
return declaration.transformChildren(this, data) as FirDeclaration
|
||||
}
|
||||
|
||||
override fun transformFile(file: FirFile, data: Any?): FirFile {
|
||||
@@ -200,15 +200,7 @@ private fun createOtherScopesForNestedClassesOrCompanion(
|
||||
// See: prepareScopes()
|
||||
}
|
||||
|
||||
fun FirRegularClass.resolveSupertypesInTheAir(session: FirSession): List<FirTypeRef> {
|
||||
return FirSupertypeResolverVisitor(session, SupertypeComputationSession(), ScopeSession()).run {
|
||||
withFile(session.firProvider.getFirClassifierContainerFile(this@resolveSupertypesInTheAir.symbol)) {
|
||||
resolveSpecificClassLikeSupertypes(this@resolveSupertypesInTheAir, superTypeRefs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class FirSupertypeResolverVisitor(
|
||||
class FirSupertypeResolverVisitor(
|
||||
private val session: FirSession,
|
||||
private val supertypeComputationSession: SupertypeComputationSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
@@ -218,11 +210,14 @@ open class FirSupertypeResolverVisitor(
|
||||
containingDeclarations: List<FirDeclaration> = emptyList(),
|
||||
) : FirDefaultVisitor<Unit, Any?>() {
|
||||
private val supertypeGenerationExtensions = session.extensionService.supertypeGenerators
|
||||
private val classDeclarationsStack = ArrayDeque<FirClass>()
|
||||
|
||||
@PrivateForInline
|
||||
val classDeclarationsStack = ArrayDeque<FirClass>()
|
||||
|
||||
init {
|
||||
containingDeclarations.forEach {
|
||||
if (it is FirClass) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
classDeclarationsStack.add(it)
|
||||
}
|
||||
}
|
||||
@@ -280,7 +275,7 @@ open class FirSupertypeResolverVisitor(
|
||||
private fun resolveAllSupertypes(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
supertypeRefs: List<FirTypeRef>,
|
||||
visited: MutableSet<FirClassLikeDeclaration> = mutableSetOf()
|
||||
visited: MutableSet<FirClassLikeDeclaration> = mutableSetOf(),
|
||||
) {
|
||||
if (!visited.add(classLikeDeclaration)) return
|
||||
val supertypes: List<ConeKotlinType> =
|
||||
@@ -333,8 +328,8 @@ open class FirSupertypeResolverVisitor(
|
||||
|
||||
private fun resolveSpecificClassLikeSupertypes(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
resolveSuperTypeRefs: (FirTransformer<ScopeClassDeclaration>, ScopeClassDeclaration) -> List<FirResolvedTypeRef>
|
||||
): List<FirTypeRef> {
|
||||
resolveSuperTypeRefs: (FirTransformer<ScopeClassDeclaration>, ScopeClassDeclaration) -> List<FirResolvedTypeRef>,
|
||||
): List<FirResolvedTypeRef> {
|
||||
when (val status = supertypeComputationSession.getSupertypesComputationStatus(classLikeDeclaration)) {
|
||||
is SupertypeComputationStatus.Computed -> return status.supertypeRefs
|
||||
is SupertypeComputationStatus.Computing -> return listOf(
|
||||
@@ -357,6 +352,7 @@ open class FirSupertypeResolverVisitor(
|
||||
else session.firProvider.getFirClassifierContainerFileIfAny(classLikeDeclaration.symbol)
|
||||
|
||||
val resolvedTypesRefs = transformer.withFile(newUseSiteFile) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
resolveSuperTypeRefs(
|
||||
transformer,
|
||||
ScopeClassDeclaration(scopes, classDeclarationsStack, containerDeclaration = classLikeDeclaration),
|
||||
@@ -367,28 +363,38 @@ open class FirSupertypeResolverVisitor(
|
||||
return resolvedTypesRefs
|
||||
}
|
||||
|
||||
open fun visitDeclarationContent(declaration: FirDeclaration, data: Any?) {
|
||||
declaration.acceptChildren(this, null)
|
||||
private fun visitDeclarationContent(declaration: FirDeclaration, data: Any?) {
|
||||
declaration.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
inline fun <T> withClass(firClass: FirClass, body: () -> T) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
withClassDeclarationCleanup(classDeclarationsStack, firClass) {
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?) {
|
||||
withClassDeclarationCleanup(classDeclarationsStack, regularClass) {
|
||||
withClass(regularClass) {
|
||||
resolveSpecificClassLikeSupertypes(regularClass, regularClass.superTypeRefs)
|
||||
visitDeclarationContent(regularClass, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?) {
|
||||
withClassDeclarationCleanup(classDeclarationsStack, anonymousObject) {
|
||||
withClass(anonymousObject) {
|
||||
resolveSpecificClassLikeSupertypes(anonymousObject, anonymousObject.superTypeRefs)
|
||||
visitDeclarationContent(anonymousObject, null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function won't call supertypeRefs on classLikeDeclaration directly
|
||||
*/
|
||||
fun resolveSpecificClassLikeSupertypes(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
supertypeRefs: List<FirTypeRef>
|
||||
): List<FirTypeRef> {
|
||||
supertypeRefs: List<FirTypeRef>,
|
||||
): List<FirResolvedTypeRef> {
|
||||
return resolveSpecificClassLikeSupertypes(classLikeDeclaration) { transformer, scopeDeclaration ->
|
||||
if (!classLikeDeclaration.isLocalClassOrAnonymousObject()) {
|
||||
session.lookupTracker?.let {
|
||||
@@ -399,13 +405,8 @@ open class FirSupertypeResolverVisitor(
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
This list is backed by mutable list and during iterating on it we can resolve supertypes of that class via IDE light classes
|
||||
as IJ Java resolve may resolve a lot of stuff by light classes
|
||||
this causes ConcurrentModificationException
|
||||
So we create a copy of supertypeRefs to avoid it
|
||||
*/
|
||||
supertypeRefs.createCopy().mapTo(mutableListOf()) {
|
||||
|
||||
supertypeRefs.mapTo(mutableListOf()) {
|
||||
val superTypeRef = it.transform<FirTypeRef, ScopeClassDeclaration>(transformer, scopeDeclaration)
|
||||
val typeParameterType = superTypeRef.coneTypeSafe<ConeTypeParameterType>()
|
||||
when {
|
||||
@@ -429,13 +430,11 @@ open class FirSupertypeResolverVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> List<T>.createCopy(): List<T> = ArrayList(this)
|
||||
|
||||
private fun addSupertypesFromExtensions(
|
||||
klass: FirClassLikeDeclaration,
|
||||
supertypeRefs: MutableList<FirResolvedTypeRef>,
|
||||
typeResolveTransformer: FirTransformer<ScopeClassDeclaration>,
|
||||
scopeDeclaration: ScopeClassDeclaration
|
||||
scopeDeclaration: ScopeClassDeclaration,
|
||||
) {
|
||||
if (supertypeGenerationExtensions.isEmpty()) return
|
||||
val typeResolveService = TypeResolveServiceForPlugins(typeResolveTransformer, scopeDeclaration)
|
||||
@@ -450,7 +449,7 @@ open class FirSupertypeResolverVisitor(
|
||||
|
||||
private class TypeResolveServiceForPlugins(
|
||||
val typeResolveTransformer: FirTransformer<ScopeClassDeclaration>,
|
||||
val scopeDeclaration: ScopeClassDeclaration
|
||||
val scopeDeclaration: ScopeClassDeclaration,
|
||||
) : FirSupertypeGenerationExtension.TypeResolveService() {
|
||||
override fun resolveUserType(type: FirUserTypeRef): FirResolvedTypeRef {
|
||||
return type.transform(typeResolveTransformer, scopeDeclaration)
|
||||
@@ -458,21 +457,24 @@ open class FirSupertypeResolverVisitor(
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?) {
|
||||
resolveTypeAliasSupertype(typeAlias, typeAlias.expandedTypeRef)
|
||||
}
|
||||
|
||||
fun resolveTypeAliasSupertype(typeAlias: FirTypeAlias, expandedTypeRef: FirTypeRef): List<FirResolvedTypeRef> {
|
||||
// TODO: this if is a temporary hack for built-in types (because we can't load file for them)
|
||||
if (typeAlias.expandedTypeRef is FirResolvedTypeRef) {
|
||||
return
|
||||
if (expandedTypeRef is FirResolvedTypeRef) {
|
||||
return listOf(expandedTypeRef)
|
||||
}
|
||||
|
||||
resolveSpecificClassLikeSupertypes(typeAlias) { transformer, scope ->
|
||||
val resolvedTypeRef =
|
||||
transformer.transformTypeRef(typeAlias.expandedTypeRef, scope) as? FirResolvedTypeRef
|
||||
?: return@resolveSpecificClassLikeSupertypes listOf(
|
||||
createErrorTypeRef(
|
||||
typeAlias.expandedTypeRef,
|
||||
"Unresolved expanded typeRef for ${typeAlias.symbol.classId}",
|
||||
DiagnosticKind.UnresolvedExpandedType
|
||||
)
|
||||
return resolveSpecificClassLikeSupertypes(typeAlias) { transformer, scope ->
|
||||
val resolvedTypeRef = transformer.transformTypeRef(expandedTypeRef, scope) as? FirResolvedTypeRef
|
||||
?: return@resolveSpecificClassLikeSupertypes listOf(
|
||||
createErrorTypeRef(
|
||||
expandedTypeRef,
|
||||
"Unresolved expanded typeRef for ${typeAlias.symbol.classId}",
|
||||
DiagnosticKind.UnresolvedExpandedType
|
||||
)
|
||||
)
|
||||
|
||||
fun visitNestedTypeAliases(type: TypeArgumentMarker) {
|
||||
if (type is ConeClassLikeType) {
|
||||
@@ -505,11 +507,11 @@ private fun createErrorTypeRef(fir: FirElement, message: String, kind: Diagnosti
|
||||
diagnostic = ConeSimpleDiagnostic(message, kind)
|
||||
}
|
||||
|
||||
class SupertypeComputationSession {
|
||||
open class SupertypeComputationSession {
|
||||
private val fileScopesMap = hashMapOf<FirFile, ScopePersistentList>()
|
||||
private val scopesForNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>()
|
||||
private val scopesForCompanionMap = hashMapOf<FirClass, ScopePersistentList>()
|
||||
val supertypeStatusMap = linkedMapOf<FirClassLikeDeclaration, SupertypeComputationStatus>()
|
||||
private val supertypeStatusMap = linkedMapOf<FirClassLikeDeclaration, SupertypeComputationStatus>()
|
||||
|
||||
val supertypesSupplier: SupertypeSupplier = object : SupertypeSupplier() {
|
||||
override fun forClass(firClass: FirClass, useSiteSession: FirSession): List<ConeClassLikeType> {
|
||||
@@ -558,52 +560,77 @@ class SupertypeComputationSession {
|
||||
|
||||
private val newClassifiersForBreakingLoops = mutableListOf<FirClassLikeDeclaration>()
|
||||
|
||||
fun breakLoops(session: FirSession) {
|
||||
val visitedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration>()
|
||||
val loopedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration>()
|
||||
val path = mutableListOf<FirClassLikeDeclaration>()
|
||||
val pathSet = mutableSetOf<FirClassLikeDeclaration>()
|
||||
/**
|
||||
* @return **true** if class is already resolved and can't be a part of loops
|
||||
*/
|
||||
protected open fun isAlreadyResolved(classLikeDeclaration: FirClassLikeDeclaration): Boolean = false
|
||||
|
||||
/**
|
||||
* @param supertypeRefs a collection where at least one element is [FirErrorTypeRef] for looped references
|
||||
*/
|
||||
protected open fun reportLoopErrorRefs(classLikeDeclaration: FirClassLikeDeclaration, supertypeRefs: List<FirResolvedTypeRef>) {
|
||||
supertypeStatusMap[classLikeDeclaration] = SupertypeComputationStatus.Computed(supertypeRefs)
|
||||
}
|
||||
|
||||
protected open fun getResolvedSuperTypeRefsForOutOfSessionDeclaration(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
): List<FirResolvedTypeRef>? = when (classLikeDeclaration) {
|
||||
is FirRegularClass -> classLikeDeclaration.superTypeRefs.filterIsInstance<FirResolvedTypeRef>()
|
||||
is FirTypeAlias -> listOfNotNull(classLikeDeclaration.expandedTypeRef as? FirResolvedTypeRef)
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param declaration declaration to be checked for loops
|
||||
* @param visited visited declarations during the current loop search
|
||||
* @param looped declarations inside loop
|
||||
*/
|
||||
protected fun breakLoopFor(
|
||||
declaration: FirClassLikeDeclaration,
|
||||
session: FirSession,
|
||||
visited: MutableSet<FirClassLikeDeclaration>, // always empty for LL FIR
|
||||
looped: MutableSet<FirClassLikeDeclaration>, // always empty for LL FIR
|
||||
pathSet: MutableSet<FirClassLikeDeclaration>,
|
||||
path: MutableList<FirClassLikeDeclaration>,
|
||||
) {
|
||||
require(path.isEmpty()) { "Path should be empty" }
|
||||
require(pathSet.isEmpty()) { "Path set should be empty" }
|
||||
|
||||
fun checkIsInLoop(
|
||||
classLikeDecl: FirClassLikeDeclaration?,
|
||||
classLikeDeclaration: FirClassLikeDeclaration?,
|
||||
wasSubtypingInvolved: Boolean,
|
||||
wereTypeArgumentsInvolved: Boolean,
|
||||
) {
|
||||
if (classLikeDecl == null) return
|
||||
if (classLikeDeclaration == null || isAlreadyResolved(classLikeDeclaration)) return
|
||||
require(!wasSubtypingInvolved || !wereTypeArgumentsInvolved) {
|
||||
"This must hold by induction, because otherwise such a loop is allowed"
|
||||
}
|
||||
|
||||
val supertypeRefs: List<FirResolvedTypeRef>
|
||||
val supertypeComputationStatus = supertypeStatusMap[classLikeDecl]
|
||||
supertypeRefs = if (supertypeComputationStatus != null) {
|
||||
require(supertypeComputationStatus is SupertypeComputationStatus.Computed) {
|
||||
"Expected computed supertypes in breakLoops for ${classLikeDecl.symbol.classId}"
|
||||
val supertypeStatus = supertypeStatusMap[classLikeDeclaration]
|
||||
val supertypeRefs: List<FirResolvedTypeRef> = if (supertypeStatus != null) {
|
||||
require(supertypeStatus is SupertypeComputationStatus.Computed) {
|
||||
"Expected computed supertypes in breakLoops for ${classLikeDeclaration.symbol.classId}"
|
||||
}
|
||||
supertypeComputationStatus.supertypeRefs
|
||||
|
||||
supertypeStatus.supertypeRefs
|
||||
} else {
|
||||
when (classLikeDecl) {
|
||||
is FirRegularClass ->
|
||||
classLikeDecl.superTypeRefs.filterIsInstance<FirResolvedTypeRef>()
|
||||
is FirTypeAlias ->
|
||||
(classLikeDecl.expandedTypeRef as? FirResolvedTypeRef)?.let { listOf(it) } ?: listOf()
|
||||
else -> return
|
||||
}
|
||||
getResolvedSuperTypeRefsForOutOfSessionDeclaration(classLikeDeclaration) ?: return
|
||||
}
|
||||
|
||||
if (classLikeDecl in visitedClassLikeDecls) {
|
||||
if (classLikeDecl in pathSet) {
|
||||
loopedClassLikeDecls.add(classLikeDecl)
|
||||
loopedClassLikeDecls.addAll(path.takeLastWhile { element -> element != classLikeDecl })
|
||||
if (classLikeDeclaration in visited) {
|
||||
if (classLikeDeclaration in pathSet) {
|
||||
looped.add(classLikeDeclaration)
|
||||
looped.addAll(path.takeLastWhile { element -> element != classLikeDeclaration })
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
path.add(classLikeDecl)
|
||||
pathSet.add(classLikeDecl)
|
||||
visitedClassLikeDecls.add(classLikeDecl)
|
||||
path.add(classLikeDeclaration)
|
||||
pathSet.add(classLikeDeclaration)
|
||||
visited.add(classLikeDeclaration)
|
||||
|
||||
val parentId = classLikeDecl.symbol.classId.relativeClassName.parent()
|
||||
val parentId = classLikeDeclaration.symbol.classId.relativeClassName.parent()
|
||||
if (!parentId.isRoot) {
|
||||
val parentSymbol = session.symbolProvider.getClassLikeSymbolByClassId(ClassId.fromString(parentId.asString()))
|
||||
if (parentSymbol is FirRegularClassSymbol) {
|
||||
@@ -611,14 +638,14 @@ class SupertypeComputationSession {
|
||||
}
|
||||
}
|
||||
|
||||
val isTypeAlias = classLikeDecl is FirTypeAlias
|
||||
val isTypeAlias = classLikeDeclaration is FirTypeAlias
|
||||
val isSubtypingCurrentlyInvolved = !isTypeAlias
|
||||
|
||||
// This is an optimization that prevents collecting
|
||||
// loops we don't want to report anyway.
|
||||
if (wereTypeArgumentsInvolved && isSubtypingCurrentlyInvolved) {
|
||||
path.removeAt(path.size - 1)
|
||||
pathSet.remove(classLikeDecl)
|
||||
pathSet.remove(classLikeDeclaration)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -652,11 +679,11 @@ class SupertypeComputationSession {
|
||||
}
|
||||
|
||||
resultSupertypeRefs.add(
|
||||
if (classLikeDecl in loopedClassLikeDecls) {
|
||||
if (classLikeDeclaration in looped) {
|
||||
isErrorInSupertypesFound = true
|
||||
createErrorTypeRef(
|
||||
supertypeRef,
|
||||
"Loop in supertype: ${classLikeDecl.symbol.classId} -> ${supertypeFir?.symbol?.classId}",
|
||||
"Loop in supertype: ${classLikeDeclaration.symbol.classId} -> ${supertypeFir?.symbol?.classId}",
|
||||
if (isTypeAlias) DiagnosticKind.RecursiveTypealiasExpansion else DiagnosticKind.LoopInSupertype
|
||||
)
|
||||
} else {
|
||||
@@ -666,19 +693,34 @@ class SupertypeComputationSession {
|
||||
}
|
||||
|
||||
if (isErrorInSupertypesFound) {
|
||||
supertypeStatusMap[classLikeDecl] = SupertypeComputationStatus.Computed(resultSupertypeRefs)
|
||||
reportLoopErrorRefs(classLikeDeclaration, resultSupertypeRefs)
|
||||
}
|
||||
|
||||
path.removeAt(path.size - 1)
|
||||
pathSet.remove(classLikeDecl)
|
||||
pathSet.remove(classLikeDeclaration)
|
||||
}
|
||||
|
||||
checkIsInLoop(declaration, wasSubtypingInvolved = false, wereTypeArgumentsInvolved = false)
|
||||
require(path.isEmpty()) { "Path should be empty" }
|
||||
}
|
||||
|
||||
fun breakLoops(session: FirSession) {
|
||||
val visitedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration>()
|
||||
val loopedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration>()
|
||||
val path = mutableListOf<FirClassLikeDeclaration>()
|
||||
val pathSet = mutableSetOf<FirClassLikeDeclaration>()
|
||||
|
||||
for (classifier in newClassifiersForBreakingLoops) {
|
||||
checkIsInLoop(classifier, wasSubtypingInvolved = false, wereTypeArgumentsInvolved = false)
|
||||
require(path.isEmpty()) {
|
||||
"Path should be empty"
|
||||
}
|
||||
breakLoopFor(
|
||||
declaration = classifier,
|
||||
session = session,
|
||||
visited = visitedClassLikeDecls,
|
||||
looped = loopedClassLikeDecls,
|
||||
pathSet = pathSet,
|
||||
path = path,
|
||||
)
|
||||
}
|
||||
|
||||
newClassifiersForBreakingLoops.clear()
|
||||
}
|
||||
}
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// LL_FIR_DIVERGENCE
|
||||
// The compiler doesn't guarantee exhaustiveness in reporting of inheritance cycles, so the compiler and LL FIR results are equally valid.
|
||||
// LL_FIR_DIVERGENCE
|
||||
// FILE: I.kt
|
||||
|
||||
open class I : <!CYCLIC_INHERITANCE_HIERARCHY!>K<!>() {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
// FILE: J.java
|
||||
|
||||
class J extends I {
|
||||
void bar() {}
|
||||
}
|
||||
|
||||
// FILE: K.kt
|
||||
|
||||
open class K : <!EXPOSED_SUPER_CLASS!>J<!>() {
|
||||
fun baz() {}
|
||||
}
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
// LL_FIR_DIVERGENCE
|
||||
// The compiler doesn't guarantee exhaustiveness in reporting of inheritance cycles, so the compiler and LL FIR results are equally valid.
|
||||
// LL_FIR_DIVERGENCE
|
||||
// FILE: ExceptionTracker.kt
|
||||
|
||||
interface ExceptionTracker : <!CYCLIC_INHERITANCE_HIERARCHY!>LockBasedStorageManager.ExceptionHandlingStrategy<!> {
|
||||
Reference in New Issue
Block a user