diff --git a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.fir.txt b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.fir.txt index 48abc735105..8739ed02fc4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.fir.txt @@ -5,7 +5,7 @@ FILE: fakeRecursiveSupertype.kt } } - public open class Your : R|His| { + public open class Your : /His> { public constructor(): R|Your| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.kt b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.kt index 9f1625d00b5..2e93c84b3b8 100644 --- a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.kt +++ b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveSupertype.kt @@ -1,7 +1,7 @@ import incorrect.directory.My -open class My : My() +open class My : My() -open class Your : His() +open class Your : His() -open class His : Your() +open class His : Your() diff --git a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveTypealias.kt b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveTypealias.kt index 66b45a20144..0c5bb142525 100644 --- a/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveTypealias.kt +++ b/compiler/fir/analysis-tests/testData/resolve/fakeRecursiveTypealias.kt @@ -2,4 +2,4 @@ import incorrect.directory.Your typealias My = incorrect.directory.My -typealias Your = Your +typealias Your = Your diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.fir.txt index f2e43195bb9..806a5e778b0 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.fir.txt @@ -1,5 +1,5 @@ FILE: K1.kt - public final class K2 : R|J1| { + public final class K2 : /J1> { public constructor(): R|K2| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.kt index 87fe2e60826..b02bc47ab66 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/KJKComplexHierarchyNestedLoop.kt @@ -1,6 +1,6 @@ // FIR_IDE_IGNORE // FILE: K1.kt -class K2: J1() { +class K2: J1() { class Q : Nested() fun bar() { foo() diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 271e79df24c..669403009ba 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -134,7 +134,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error { parameter("reason") } - + val CYCLIC_INHERITANCE_HIERARCHY by error() } val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") { @@ -867,6 +867,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val TYPE_ALIAS by object : DiagnosticGroup("Type alias") { val TOPLEVEL_TYPEALIASES_ONLY by error() + val RECURSIVE_TYPEALIAS_EXPANSION by error() } val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index ca038204b85..5f28ae3f37b 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -143,6 +143,7 @@ object FirErrors { val SEALED_SUPERTYPE by error0() val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0() val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1() + val CYCLIC_INHERITANCE_HIERARCHY by error0() // Constructor problems val CONSTRUCTOR_IN_OBJECT by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) @@ -481,6 +482,7 @@ object FirErrors { // Type alias val TOPLEVEL_TYPEALIASES_ONLY by error0() + val RECURSIVE_TYPEALIAS_EXPANSION by error0() // Extended checkers val REDUNDANT_VISIBILITY_MODIFIER by warning0(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonTypeCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonTypeCheckers.kt index 3f45ff54663..5a0e3822d40 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonTypeCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonTypeCheckers.kt @@ -5,14 +5,11 @@ package org.jetbrains.kotlin.fir.analysis.checkers -import org.jetbrains.kotlin.fir.analysis.checkers.type.FirSuspendModifierChecker -import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeAnnotationChecker -import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker -import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.type.* object CommonTypeCheckers : TypeCheckers() { override val typeRefCheckers: Set = setOf( FirTypeAnnotationChecker, - FirSuspendModifierChecker, + FirSuspendModifierChecker ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index db846fa1a37..eaea85c43a6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NO import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_INHERITANCE_HIERARCHY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS @@ -247,6 +248,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.QUALIFIED_SUPERTY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_INLINE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSIVE_TYPEALIAS_EXPANSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDECLARATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_ANNOTATION_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD @@ -438,7 +440,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(SEALED_SUPERTYPE, "This type is sealed, so it can be inherited by only its own nested classes or objects") map.put(SEALED_SUPERTYPE_IN_LOCAL_CLASS, "Local class cannot extend a sealed class") map.put(SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, "Supertype is not a class or interface", TO_STRING) - + map.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type") // Constructor problems map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects") @@ -1109,6 +1111,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { // Type alias map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported") + map.put(RECURSIVE_TYPEALIAS_EXPANSION, "Recursive type alias in expansion") // Returns map.put(RETURN_NOT_ALLOWED, "'return' is not allowed here") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 19585133cb7..7ab0b496a6f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -62,7 +62,7 @@ private fun ConeDiagnostic.toFirDiagnostic( FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) is ConeSimpleDiagnostic -> when (source.kind) { is FirFakeSourceElementKind -> null - else -> this.getFactory(source).on(qualifiedAccessSource ?: source) + else -> this.getFactory(source)?.on(qualifiedAccessSource ?: source) } is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target) is ConeStubDiagnostic -> null @@ -277,7 +277,7 @@ private fun ConstraintSystemError.toDiagnostic( private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType private val NewConstraintError.upperConeType: ConeKotlinType get() = upperType as ConeKotlinType -private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagnosticFactory0<*> { +private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagnosticFactory0<*>? { @Suppress("UNCHECKED_CAST") return when (kind) { DiagnosticKind.Syntax -> FirErrors.SYNTAX @@ -309,11 +309,15 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno DiagnosticKind.IntLiteralOutOfRange -> FirErrors.INT_LITERAL_OUT_OF_RANGE DiagnosticKind.FloatLiteralOutOfRange -> FirErrors.FLOAT_LITERAL_OUT_OF_RANGE DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX - DiagnosticKind.Other -> FirErrors.OTHER_ERROR DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL DiagnosticKind.IllegalEscape -> FirErrors.ILLEGAL_ESCAPE + DiagnosticKind.RecursiveTypealiasExpansion -> FirErrors.RECURSIVE_TYPEALIAS_EXPANSION + DiagnosticKind.LoopInSupertype -> FirErrors.CYCLIC_INHERITANCE_HIERARCHY + DiagnosticKind.UnresolvedSupertype, + DiagnosticKind.UnresolvedExpandedType, + DiagnosticKind.Other -> FirErrors.OTHER_ERROR else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt index 1a9c287a31d..3b6e9fff9f5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt @@ -11,6 +11,7 @@ import kotlinx.collections.immutable.toPersistentList import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider @@ -27,13 +28,16 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef -import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer +import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor +import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.model.TypeArgumentMarker import org.jetbrains.kotlin.utils.addIfNotNull -import org.jetbrains.kotlin.utils.addToStdlib.safeAs class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) { @@ -273,7 +277,11 @@ class FirSupertypeResolverVisitor( when (val status = supertypeComputationSession.getSupertypesComputationStatus(classLikeDeclaration)) { is SupertypeComputationStatus.Computed -> return status.supertypeRefs is SupertypeComputationStatus.Computing -> return listOf( - createErrorTypeRef(classLikeDeclaration, "Loop in supertype definition for ${classLikeDeclaration.symbol.classId}") + createErrorTypeRef( + classLikeDeclaration, + "Loop in supertype definition for ${classLikeDeclaration.symbol.classId}", + if (classLikeDeclaration is FirTypeAlias) DiagnosticKind.RecursiveTypealiasExpansion else DiagnosticKind.LoopInSupertype + ) ) } @@ -326,7 +334,11 @@ class FirSupertypeResolverVisitor( diagnostic = ConeTypeParameterSupertype(typeParameterType.lookupTag.typeParameterSymbol) } superTypeRef !is FirResolvedTypeRef -> - createErrorTypeRef(superTypeRef, "Unresolved super-type: ${superTypeRef.render()}") + createErrorTypeRef( + superTypeRef, + "Unresolved super-type: ${superTypeRef.render()}", + DiagnosticKind.UnresolvedSupertype + ) else -> superTypeRef } @@ -360,18 +372,26 @@ class FirSupertypeResolverVisitor( ?: return@resolveSpecificClassLikeSupertypes listOf( createErrorTypeRef( typeAlias.expandedTypeRef, - "Unresolved expanded typeRef for ${typeAlias.symbol.classId}" + "Unresolved expanded typeRef for ${typeAlias.symbol.classId}", + DiagnosticKind.UnresolvedExpandedType ) ) - val type = resolvedTypeRef.type - if (type is ConeClassLikeType) { - val expansionTypeAlias = type.lookupTag.toSymbol(session)?.safeAs()?.fir - if (expansionTypeAlias != null) { - visitTypeAlias(expansionTypeAlias, null) + fun visitNestedTypeAliases(type: TypeArgumentMarker) { + if (type is ConeClassLikeType) { + val symbol = type.lookupTag.toSymbol(session) + if (symbol is FirTypeAliasSymbol) { + visitTypeAlias(symbol.fir, null) + } else if (symbol is FirClassLikeSymbol) { + for (typeArgument in type.typeArguments) { + visitNestedTypeAliases(typeArgument) + } + } } } + visitNestedTypeAliases(resolvedTypeRef.type) + listOf(resolvedTypeRef) } } @@ -381,9 +401,9 @@ class FirSupertypeResolverVisitor( } } -private fun createErrorTypeRef(fir: FirElement, message: String) = buildErrorTypeRef { +private fun createErrorTypeRef(fir: FirElement, message: String, kind: DiagnosticKind) = buildErrorTypeRef { source = fir.source - diagnostic = ConeSimpleDiagnostic(message) + diagnostic = ConeSimpleDiagnostic(message, kind) } class SupertypeComputationSession { @@ -434,51 +454,95 @@ class SupertypeComputationSession { } private val newClassifiersForBreakingLoops = mutableListOf>() - private val breakLoopsDfsVisited = hashSetOf>() fun breakLoops(session: FirSession) { - val inProcess = hashSetOf>() + val visitedClassLikeDecls = mutableSetOf>() + val loopedClassLikeDecls = mutableSetOf>() + val path = mutableListOf>() + val pathSet = mutableSetOf>() - fun dfs(classLikeDeclaration: FirClassLikeDeclaration<*>) { - if (classLikeDeclaration in breakLoopsDfsVisited) return - val supertypeComputationStatus = supertypeStatusMap[classLikeDeclaration] ?: return - if (classLikeDeclaration in inProcess) return + fun checkIsInLoop(classLikeDecl: FirClassLikeDeclaration<*>?) { + if (classLikeDecl == null) return - inProcess.add(classLikeDeclaration) - - require(supertypeComputationStatus is SupertypeComputationStatus.Computed) { - "Expected computed supertypes in breakLoops for ${classLikeDeclaration.symbol.classId}" + val supertypeRefs: List + val supertypeComputationStatus = supertypeStatusMap[classLikeDecl] + supertypeRefs = if (supertypeComputationStatus != null) { + require(supertypeComputationStatus is SupertypeComputationStatus.Computed) { + "Expected computed supertypes in breakLoops for ${classLikeDecl.symbol.classId}" + } + supertypeComputationStatus.supertypeRefs + } else { + when (classLikeDecl) { + is FirRegularClass -> + classLikeDecl.superTypeRefs.filterIsInstance() + is FirTypeAlias -> + (classLikeDecl.expandedTypeRef as? FirResolvedTypeRef)?.let { listOf(it) } ?: listOf() + else -> return + } } - val typeRefs = supertypeComputationStatus.supertypeRefs - val resultingTypeRefs = mutableListOf() - var wereChanges = false + if (classLikeDecl in visitedClassLikeDecls) { + if (classLikeDecl in pathSet) { + loopedClassLikeDecls.add(classLikeDecl) + loopedClassLikeDecls.addAll(path.takeLastWhile { element -> element != classLikeDecl }) + } + return + } - for (typeRef in typeRefs) { - val fir = typeRef.firClassLike(session) - fir?.let(::dfs) - resultingTypeRefs.add( - if (fir in inProcess) { - wereChanges = true + path.add(classLikeDecl) + pathSet.add(classLikeDecl) + visitedClassLikeDecls.add(classLikeDecl) + + val parentId = classLikeDecl.symbol.classId.relativeClassName.parent() + if (!parentId.isRoot) { + val parentSymbol = session.symbolProvider.getClassLikeSymbolByFqName(ClassId.fromString(parentId.asString())) + if (parentSymbol is FirRegularClassSymbol) { + checkIsInLoop(parentSymbol.fir) + } + } + + val isTypeAlias = classLikeDecl is FirTypeAlias + var isErrorInSupertypesFound = false + val resultSupertypeRefs = mutableListOf() + for (supertypeRef in supertypeRefs) { + val supertypeFir = supertypeRef.firClassLike(session) + checkIsInLoop(supertypeFir) + + if (isTypeAlias) { + for (typeArgument in supertypeRef.type.typeArguments) { + if (typeArgument is ConeClassLikeType) { + checkIsInLoop(typeArgument.lookupTag.toSymbol(session)?.fir) + } + } + } + + resultSupertypeRefs.add( + if (classLikeDecl in loopedClassLikeDecls) { + isErrorInSupertypesFound = true createErrorTypeRef( - typeRef, - "Loop in supertype: ${classLikeDeclaration.symbol.classId} -> ${fir?.symbol?.classId}" + supertypeRef, + "Loop in supertype: ${classLikeDecl.symbol.classId} -> ${supertypeFir?.symbol?.classId}", + if (isTypeAlias) DiagnosticKind.RecursiveTypealiasExpansion else DiagnosticKind.LoopInSupertype ) - } else - typeRef + } else { + supertypeRef + } ) } - if (wereChanges) { - supertypeStatusMap[classLikeDeclaration] = SupertypeComputationStatus.Computed(resultingTypeRefs) + if (isErrorInSupertypesFound) { + supertypeStatusMap[classLikeDecl] = SupertypeComputationStatus.Computed(resultSupertypeRefs) } - inProcess.remove(classLikeDeclaration) - breakLoopsDfsVisited.add(classLikeDeclaration) + path.removeAt(path.size - 1) + pathSet.remove(classLikeDecl) } for (classifier in newClassifiersForBreakingLoops) { - dfs(classifier) + checkIsInLoop(classifier) + require(path.isEmpty()) { + "Path should be empty" + } } newClassifiersForBreakingLoops.clear() } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt index b1fa3b9a7d3..da4d407ff09 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt @@ -36,6 +36,11 @@ enum class DiagnosticKind { IllegalProjectionUsage, MissingStdlibClass, + LoopInSupertype, + RecursiveTypealiasExpansion, + UnresolvedSupertype, + UnresolvedExpandedType, + IncorrectCharacterLiteral, EmptyCharacterLiteral, TooManyCharactersInCharacterLiteral, diff --git a/compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.fir.kt b/compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.fir.kt index 3efa41504ea..390ec1a0842 100644 --- a/compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.fir.kt +++ b/compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.fir.kt @@ -1,6 +1,6 @@ -open class RecA: RecB() -open class RecB: RecA() -open class SelfR: SelfR() +open class RecA: RecB() +open class RecB: RecA() +open class SelfR: SelfR() fun test(f: SelfR) = f is RecA -fun test(f: RecB) = f is RecA \ No newline at end of file +fun test(f: RecB) = f is RecA diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.fir.kt deleted file mode 100644 index 3eb40751586..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.fir.kt +++ /dev/null @@ -1,4 +0,0 @@ -open class C : D() { - open class CC -} -open class D : C.CC() diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.kt index 695b17efc6f..2e73e58bbc4 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/classIndirectlyInheritsNested.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class C : D() { open class CC } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.fir.kt deleted file mode 100644 index 8fa8ed8d9d5..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -open class E : E.EE() { - open class EE -} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.kt index 45cd12d9f85..18e9cc19a6b 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/classInheritsNested.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class E : E.EE() { open class EE } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.fir.kt deleted file mode 100644 index 77feb341b84..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.fir.kt +++ /dev/null @@ -1,8 +0,0 @@ -open class A : B() -open class B : A() - -fun select(vararg xs: T): T = xs[0] - -fun foo() { - val x = select(A(), B(), "foo") -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.kt index e21856a33a7..c3e8e035285 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicAndUsualTypes.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class A : B() open class B : A() diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.fir.kt deleted file mode 100644 index 0f45068f764..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.fir.kt +++ /dev/null @@ -1,8 +0,0 @@ -open class A : B() -open class B : A() - -fun select(vararg xs: T): T = xs[0] - -fun foo() { - select(A(), B()) -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.kt index 1718b0246e9..f1898cf7f8e 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/commonSupertypeForCyclicTypes.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class A : B() open class B : A() diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.fir.kt deleted file mode 100644 index 0eaf10e17e0..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.fir.kt +++ /dev/null @@ -1,30 +0,0 @@ -interface A { - fun foo() {} -} -interface B : A, E {} -interface C : B {} -interface D : B {} -interface E : F {} -interface F : D, C {} -interface G : F {} -interface H : F {} - -val a : A? = null -val b : B? = null -val c : C? = null -val d : D? = null -val e : E? = null -val f : F? = null -val g : G? = null -val h : H? = null - -fun test() { - a?.foo() - b?.foo() - c?.foo() - d?.foo() - e?.foo() - f?.foo() - g?.foo() - h?.foo() -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt index 1069f78978e..5d25a2ff17c 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface A { fun foo() {} } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.fir.kt deleted file mode 100644 index 0ee5c285c19..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// FILE: A.java - -interface A extends C { - void foo(); -} - -// FILE: B.kt - -interface B : A { - fun bar() -} - -// FILE: C.java - -interface C extends B { - void baz(); -} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt index 5ad56e7b4c6..2834a5354b4 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: A.java interface A extends C { diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.fir.kt deleted file mode 100644 index 8002261c5b9..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -// FILE: J.java - -class J extends K { - void foo() {} -} - -// FILE: K.kt - -class K : J() { - fun bar() {} -} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt index 6d1e0dfeb12..e0d1595e0e8 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: J.java class J extends K { diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.fir.kt index 1b48daaedd1..c56c6f3492f 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.fir.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.fir.kt @@ -12,6 +12,6 @@ class J extends I { // FILE: K.kt -open class K : J() { +open class K : J() { fun baz() {} } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.fir.kt index cf752aecdd6..208e0735310 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.fir.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.fir.kt @@ -5,7 +5,7 @@ interface ExceptionTracker : LockBasedStorageManager. // FILE: StorageManager.kt -interface StorageManager : ExceptionTracker { +interface StorageManager : ExceptionTracker { fun foo() } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.fir.kt index 679eab7d581..31e4c796352 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.fir.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.fir.kt @@ -1,10 +1,10 @@ // KT-303 Stack overflow on a cyclic class hierarchy -open class Foo() : Bar() { +open class Foo() : Bar() { val a : Int = 1 } -open class Bar() : Foo() { +open class Bar() : Foo() { } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.fir.kt deleted file mode 100644 index 554aa01effa..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.fir.kt +++ /dev/null @@ -1,22 +0,0 @@ -// As in KT-18514 -object A : A.I { - interface I -} - -// Similar to 'classIndirectlyInheritsNested.kt' -object D : E() { - open class NestedD -} - -open class E : D.NestedD() - - - -// Similar to 'twoClassesWithNestedCycle.kt' -object G : H.NestedH() { - open class NestedG -} -object H : G.NestedG() { - open class NestedH -} - diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.kt index 1ceca3b90b9..3f1a4c3d944 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/objectInheritsNested.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // As in KT-18514 object A : A.I { interface I diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.fir.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.fir.kt deleted file mode 100644 index d989abdff0c..00000000000 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.fir.kt +++ /dev/null @@ -1,6 +0,0 @@ -open class A : B.BB() { - open class AA -} -open class B : A.AA() { - open class BB -} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.kt index 0d07585e2c4..2feb28cdf7e 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.kt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class A : B.BB() { open class AA } diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/dslMarkerWithTypealiasRecursion.fir.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/dslMarkerWithTypealiasRecursion.fir.kt index 1a9fac5a9ca..ae39851122e 100644 --- a/compiler/testData/diagnostics/tests/resolve/dslMarker/dslMarkerWithTypealiasRecursion.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/dslMarkerWithTypealiasRecursion.fir.kt @@ -8,8 +8,8 @@ class Foo class Bar -typealias YBar = ZBar -typealias ZBar = YBar +typealias YBar = ZBar +typealias ZBar = YBar fun Foo.foo(body: Foo.() -> Unit) = body() fun Foo.zbar(body: ZBar.() -> Unit) = Bar().body() diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt index 52b385ddfa7..6c0fe35fb82 100644 --- a/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/companionObjectParents.fir.kt @@ -7,7 +7,7 @@ val bImpl: B.Companion.Interface get() = null!! interface A { - companion object : Nested(), Interface by aImpl, I { + companion object : Nested(), Interface by aImpl, I { class Nested @@ -16,7 +16,7 @@ interface A { } class B { - companion object : Nested(), Interface by aImpl, I { + companion object : Nested(), Interface by aImpl, I { class Nested diff --git a/compiler/testData/diagnostics/tests/typealias/cyclicInheritanceViaTypeAlias.fir.kt b/compiler/testData/diagnostics/tests/typealias/cyclicInheritanceViaTypeAlias.fir.kt index 2943e8b4c4e..c652d29af66 100644 --- a/compiler/testData/diagnostics/tests/typealias/cyclicInheritanceViaTypeAlias.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/cyclicInheritanceViaTypeAlias.fir.kt @@ -1,7 +1,7 @@ -class A : B() { +class A : B() { open class Nested } -typealias ANested = A.Nested +typealias ANested = A.Nested -open class B : ANested() \ No newline at end of file +open class B : ANested() diff --git a/compiler/testData/diagnostics/tests/typealias/recursive.fir.kt b/compiler/testData/diagnostics/tests/typealias/recursive.fir.kt index e0297a7c193..a4c437cf15c 100644 --- a/compiler/testData/diagnostics/tests/typealias/recursive.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/recursive.fir.kt @@ -1,11 +1,12 @@ -typealias R = R +typealias R = R -typealias L = List +typealias L = List -typealias A = B -typealias B = A +typealias A = B +typealias B = A -typealias F1 = (Int) -> F2 -typealias F2 = (F1) -> Int +typealias F1 = (Int) -> F2 +typealias F2 = (F1) -> Int +typealias F3 = (F1) -> Int -val x: A = TODO() +val x: F3 = TODO() diff --git a/compiler/testData/diagnostics/tests/typealias/recursive.kt b/compiler/testData/diagnostics/tests/typealias/recursive.kt index 3522e2dbf12..fcb1651ed59 100644 --- a/compiler/testData/diagnostics/tests/typealias/recursive.kt +++ b/compiler/testData/diagnostics/tests/typealias/recursive.kt @@ -7,5 +7,6 @@ typealias B = A typealias F1 = (Int) -> F2 typealias F2 = (F1) -> Int +typealias F3 = (F1) -> Int -val x: A = TODO() +val x: F3 = TODO() diff --git a/compiler/testData/diagnostics/tests/typealias/recursive.txt b/compiler/testData/diagnostics/tests/typealias/recursive.txt index f7eda2c0410..bab06724e69 100644 --- a/compiler/testData/diagnostics/tests/typealias/recursive.txt +++ b/compiler/testData/diagnostics/tests/typealias/recursive.txt @@ -1,9 +1,11 @@ package -public val x: [ERROR : Recursive type alias: A] +public val x: F3 /* = (F1 /* = (kotlin.Int) -> F2 /* = ([ERROR : Recursive type alias: F1]) -> kotlin.Int */ */) -> kotlin.Int */ public typealias A = B public typealias B = A public typealias F1 = (kotlin.Int) -> F2 public typealias F2 = (F1) -> kotlin.Int +public typealias F3 = (F1) -> kotlin.Int public typealias L = kotlin.collections.List public typealias R = R + diff --git a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.fir.kt deleted file mode 100644 index f02cd10b96a..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.fir.kt +++ /dev/null @@ -1,51 +0,0 @@ -// !LANGUAGE: +NewInference +ProhibitInvisibleAbstractMethodsInSuperclasses -// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION -// SKIP_TXT -// FULL_JDK - -// TESTCASE NUMBER: 1 -class Case1() : BaseCase1(), InterfaceCase1 {} - -abstract class BaseCase1() { - abstract fun foo(): String - abstract val a: String -} - -interface InterfaceCase1 { - fun foo() = "foo" - val a: String - get() = "a" -} - -// TESTCASE NUMBER: 2 -class Case2Outer { - val v = "v" - - abstract class Case2Base() { - abstract fun foo(): String - } - - inner - class A() : Case2Base() { - - } -} - -// TESTCASE NUMBER: 3 -fun case3() { - object : CaseOuter.CaseBase() {}.outerFoo() -} - -class B() : CaseOuter.CaseBase() {} - -sealed class CaseOuter { - val v = "v" - abstract fun outerFoo(); - - abstract class CaseBase() : CaseOuter() { - abstract fun foo(): String - } - - class A() : CaseBase() { - } -} diff --git a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.kt b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.kt index 75a4a22980c..75abc937006 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.10.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference +ProhibitInvisibleAbstractMethodsInSuperclasses // !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // SKIP_TXT diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 5f364455b75..8771ccc1b72 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -407,6 +407,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.CYCLIC_INHERITANCE_HIERARCHY) { firDiagnostic -> + CyclicInheritanceHierarchyImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic -> ConstructorInObjectImpl( firDiagnostic as FirPsiDiagnostic<*>, @@ -2378,6 +2384,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.RECURSIVE_TYPEALIAS_EXPANSION) { firDiagnostic -> + RecursiveTypealiasExpansionImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.REDUNDANT_VISIBILITY_MODIFIER) { firDiagnostic -> RedundantVisibilityModifierImpl( firDiagnostic as FirPsiDiagnostic<*>, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 6d9366f470f..b64592dbc22 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -303,6 +303,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val reason: String } + abstract class CyclicInheritanceHierarchy : KtFirDiagnostic() { + override val diagnosticClass get() = CyclicInheritanceHierarchy::class + } + abstract class ConstructorInObject : KtFirDiagnostic() { override val diagnosticClass get() = ConstructorInObject::class } @@ -1670,6 +1674,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ToplevelTypealiasesOnly::class } + abstract class RecursiveTypealiasExpansion : KtFirDiagnostic() { + override val diagnosticClass get() = RecursiveTypealiasExpansion::class + } + abstract class RedundantVisibilityModifier : KtFirDiagnostic() { override val diagnosticClass get() = RedundantVisibilityModifier::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 72527ea5471..d9161e6c21e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -472,6 +472,13 @@ internal class SupertypeNotAClassOrInterfaceImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class CyclicInheritanceHierarchyImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.CyclicInheritanceHierarchy(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ConstructorInObjectImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, @@ -2703,6 +2710,13 @@ internal class ToplevelTypealiasesOnlyImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class RecursiveTypealiasExpansionImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.RecursiveTypealiasExpansion(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class RedundantVisibilityModifierImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, diff --git a/idea/testData/checker/CyclicHierarchy.fir.kt b/idea/testData/checker/CyclicHierarchy.fir.kt index 90756e11de4..5fb3841ad2a 100644 --- a/idea/testData/checker/CyclicHierarchy.fir.kt +++ b/idea/testData/checker/CyclicHierarchy.fir.kt @@ -1,11 +1,11 @@ interface A { fun foo() {} } -interface B : A, E {} -interface C : B {} -interface D : B {} -interface E : F {} -interface F : D, C {} +interface B : A, E {} +interface C : B {} +interface D : B {} +interface E : F {} +interface F : D, C {} interface G : F {} interface H : F {} diff --git a/idea/testData/checker/regression/kt303.fir.kt b/idea/testData/checker/regression/kt303.fir.kt index a7b98983f99..b50cc5b70f8 100644 --- a/idea/testData/checker/regression/kt303.fir.kt +++ b/idea/testData/checker/regression/kt303.fir.kt @@ -1,10 +1,10 @@ // KT-303 Stack overflow on a cyclic class hierarchy -open class Foo() : Bar() { +open class Foo() : Bar() { val a : Int = 1 } -open class Bar() : Foo() { +open class Bar() : Foo() { } diff --git a/idea/testData/checker/trivialHierarchyLoop.fir.kt b/idea/testData/checker/trivialHierarchyLoop.fir.kt index 8547f61a93c..08cf599f28c 100644 --- a/idea/testData/checker/trivialHierarchyLoop.fir.kt +++ b/idea/testData/checker/trivialHierarchyLoop.fir.kt @@ -1,3 +1,3 @@ -class A : A() {} +class A : A() {} val x : Int = A()