[FIR] Implement RECURSIVE_TYPEALIAS_EXPANSION, CYCLIC_INHERITANCE_HIERARCHY diagnostics, fix stackoverlow exception in case if typealias points to type with type arguments

This commit is contained in:
Ivan Kochurkin
2021-05-26 12:34:19 +03:00
committed by teamcityserver
parent d1531f9cdd
commit c4c2fbb5a0
48 changed files with 213 additions and 249 deletions
@@ -5,7 +5,7 @@ FILE: fakeRecursiveSupertype.kt
} }
} }
public open class Your : R|His| { public open class Your : <ERROR TYPE REF: Loop in supertype: /Your -> /His> {
public constructor(): R|Your| { public constructor(): R|Your| {
super<R|His|>() super<R|His|>()
} }
@@ -1,7 +1,7 @@
import incorrect.directory.My import incorrect.directory.My
open class My : <!OTHER_ERROR!>My<!>() open class My : <!CYCLIC_INHERITANCE_HIERARCHY!>My<!>()
open class Your : His() open class Your : <!CYCLIC_INHERITANCE_HIERARCHY!>His<!>()
open class His : <!OTHER_ERROR!>Your<!>() open class His : <!CYCLIC_INHERITANCE_HIERARCHY!>Your<!>()
@@ -2,4 +2,4 @@ import incorrect.directory.Your
typealias My = <!UNRESOLVED_REFERENCE!>incorrect.directory.My<!> typealias My = <!UNRESOLVED_REFERENCE!>incorrect.directory.My<!>
typealias Your = <!OTHER_ERROR!>Your<!> typealias Your = <!RECURSIVE_TYPEALIAS_EXPANSION!>Your<!>
@@ -1,5 +1,5 @@
FILE: K1.kt FILE: K1.kt
public final class K2 : R|J1| { public final class K2 : <ERROR TYPE REF: Loop in supertype: /K2 -> /J1> {
public constructor(): R|K2| { public constructor(): R|K2| {
super<R|J1|>() super<R|J1|>()
} }
@@ -1,6 +1,6 @@
// FIR_IDE_IGNORE // FIR_IDE_IGNORE
// FILE: K1.kt // FILE: K1.kt
class K2: J1() { class K2: <!CYCLIC_INHERITANCE_HIERARCHY!>J1<!>() {
class Q : <!UNRESOLVED_REFERENCE!>Nested<!>() class Q : <!UNRESOLVED_REFERENCE!>Nested<!>()
fun bar() { fun bar() {
<!UNRESOLVED_REFERENCE!>foo<!>() <!UNRESOLVED_REFERENCE!>foo<!>()
@@ -134,7 +134,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error<KtElement> { val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error<KtElement> {
parameter<String>("reason") parameter<String>("reason")
} }
val CYCLIC_INHERITANCE_HIERARCHY by error<PsiElement>()
} }
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") { 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 TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
val TOPLEVEL_TYPEALIASES_ONLY by error<KtTypeAlias>() val TOPLEVEL_TYPEALIASES_ONLY by error<KtTypeAlias>()
val RECURSIVE_TYPEALIAS_EXPANSION by error<KtTypeAlias>()
} }
val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") { val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") {
@@ -143,6 +143,7 @@ object FirErrors {
val SEALED_SUPERTYPE by error0<KtTypeReference>() val SEALED_SUPERTYPE by error0<KtTypeReference>()
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<KtTypeReference>() val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<KtTypeReference>()
val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1<KtElement, String>() val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1<KtElement, String>()
val CYCLIC_INHERITANCE_HIERARCHY by error0<PsiElement>()
// Constructor problems // Constructor problems
val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
@@ -481,6 +482,7 @@ object FirErrors {
// Type alias // Type alias
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>() val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
val RECURSIVE_TYPEALIAS_EXPANSION by error0<KtTypeAlias>()
// Extended checkers // Extended checkers
val REDUNDANT_VISIBILITY_MODIFIER by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_VISIBILITY_MODIFIER by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
@@ -5,14 +5,11 @@
package org.jetbrains.kotlin.fir.analysis.checkers package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirSuspendModifierChecker import org.jetbrains.kotlin.fir.analysis.checkers.type.*
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
object CommonTypeCheckers : TypeCheckers() { object CommonTypeCheckers : TypeCheckers() {
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf( override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
FirTypeAnnotationChecker, FirTypeAnnotationChecker,
FirSuspendModifierChecker, FirSuspendModifierChecker
) )
} }
@@ -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.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_CONSTRUCTOR_DELEGATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND 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_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_VARARG_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS 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_IMPLICIT_TYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_INLINE 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.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.REDECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_ANNOTATION_TARGET import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_ANNOTATION_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD 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, "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(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(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 // Constructor problems
map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects") map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects")
@@ -1109,6 +1111,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
// Type alias // Type alias
map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported") map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported")
map.put(RECURSIVE_TYPEALIAS_EXPANSION, "Recursive type alias in expansion")
// Returns // Returns
map.put(RETURN_NOT_ALLOWED, "'return' is not allowed here") map.put(RETURN_NOT_ALLOWED, "'return' is not allowed here")
@@ -62,7 +62,7 @@ private fun ConeDiagnostic.toFirDiagnostic(
FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type)
is ConeSimpleDiagnostic -> when (source.kind) { is ConeSimpleDiagnostic -> when (source.kind) {
is FirFakeSourceElementKind -> null 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 ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target)
is ConeStubDiagnostic -> null is ConeStubDiagnostic -> null
@@ -277,7 +277,7 @@ private fun ConstraintSystemError.toDiagnostic(
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType
private val NewConstraintError.upperConeType: ConeKotlinType get() = upperType 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") @Suppress("UNCHECKED_CAST")
return when (kind) { return when (kind) {
DiagnosticKind.Syntax -> FirErrors.SYNTAX DiagnosticKind.Syntax -> FirErrors.SYNTAX
@@ -309,11 +309,15 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno
DiagnosticKind.IntLiteralOutOfRange -> FirErrors.INT_LITERAL_OUT_OF_RANGE DiagnosticKind.IntLiteralOutOfRange -> FirErrors.INT_LITERAL_OUT_OF_RANGE
DiagnosticKind.FloatLiteralOutOfRange -> FirErrors.FLOAT_LITERAL_OUT_OF_RANGE DiagnosticKind.FloatLiteralOutOfRange -> FirErrors.FLOAT_LITERAL_OUT_OF_RANGE
DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL
DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL
DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL
DiagnosticKind.IllegalEscape -> FirErrors.ILLEGAL_ESCAPE 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") else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass")
} }
} }
@@ -11,6 +11,7 @@ import kotlinx.collections.immutable.toPersistentList
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
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.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider 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.nestedClassifierScope
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol 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.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef 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.name.ClassId
import org.jetbrains.kotlin.types.model.TypeArgumentMarker
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSession) : class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSession) :
FirTransformerBasedResolveProcessor(session, scopeSession) { FirTransformerBasedResolveProcessor(session, scopeSession) {
@@ -273,7 +277,11 @@ class FirSupertypeResolverVisitor(
when (val status = supertypeComputationSession.getSupertypesComputationStatus(classLikeDeclaration)) { when (val status = supertypeComputationSession.getSupertypesComputationStatus(classLikeDeclaration)) {
is SupertypeComputationStatus.Computed -> return status.supertypeRefs is SupertypeComputationStatus.Computed -> return status.supertypeRefs
is SupertypeComputationStatus.Computing -> return listOf( 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) diagnostic = ConeTypeParameterSupertype(typeParameterType.lookupTag.typeParameterSymbol)
} }
superTypeRef !is FirResolvedTypeRef -> superTypeRef !is FirResolvedTypeRef ->
createErrorTypeRef(superTypeRef, "Unresolved super-type: ${superTypeRef.render()}") createErrorTypeRef(
superTypeRef,
"Unresolved super-type: ${superTypeRef.render()}",
DiagnosticKind.UnresolvedSupertype
)
else -> else ->
superTypeRef superTypeRef
} }
@@ -360,18 +372,26 @@ class FirSupertypeResolverVisitor(
?: return@resolveSpecificClassLikeSupertypes listOf( ?: return@resolveSpecificClassLikeSupertypes listOf(
createErrorTypeRef( createErrorTypeRef(
typeAlias.expandedTypeRef, typeAlias.expandedTypeRef,
"Unresolved expanded typeRef for ${typeAlias.symbol.classId}" "Unresolved expanded typeRef for ${typeAlias.symbol.classId}",
DiagnosticKind.UnresolvedExpandedType
) )
) )
val type = resolvedTypeRef.type fun visitNestedTypeAliases(type: TypeArgumentMarker) {
if (type is ConeClassLikeType) { if (type is ConeClassLikeType) {
val expansionTypeAlias = type.lookupTag.toSymbol(session)?.safeAs<FirTypeAliasSymbol>()?.fir val symbol = type.lookupTag.toSymbol(session)
if (expansionTypeAlias != null) { if (symbol is FirTypeAliasSymbol) {
visitTypeAlias(expansionTypeAlias, null) visitTypeAlias(symbol.fir, null)
} else if (symbol is FirClassLikeSymbol) {
for (typeArgument in type.typeArguments) {
visitNestedTypeAliases(typeArgument)
}
}
} }
} }
visitNestedTypeAliases(resolvedTypeRef.type)
listOf(resolvedTypeRef) 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 source = fir.source
diagnostic = ConeSimpleDiagnostic(message) diagnostic = ConeSimpleDiagnostic(message, kind)
} }
class SupertypeComputationSession { class SupertypeComputationSession {
@@ -434,51 +454,95 @@ class SupertypeComputationSession {
} }
private val newClassifiersForBreakingLoops = mutableListOf<FirClassLikeDeclaration<*>>() private val newClassifiersForBreakingLoops = mutableListOf<FirClassLikeDeclaration<*>>()
private val breakLoopsDfsVisited = hashSetOf<FirClassLikeDeclaration<*>>()
fun breakLoops(session: FirSession) { fun breakLoops(session: FirSession) {
val inProcess = hashSetOf<FirClassLikeDeclaration<*>>() val visitedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration<*>>()
val loopedClassLikeDecls = mutableSetOf<FirClassLikeDeclaration<*>>()
val path = mutableListOf<FirClassLikeDeclaration<*>>()
val pathSet = mutableSetOf<FirClassLikeDeclaration<*>>()
fun dfs(classLikeDeclaration: FirClassLikeDeclaration<*>) { fun checkIsInLoop(classLikeDecl: FirClassLikeDeclaration<*>?) {
if (classLikeDeclaration in breakLoopsDfsVisited) return if (classLikeDecl == null) return
val supertypeComputationStatus = supertypeStatusMap[classLikeDeclaration] ?: return
if (classLikeDeclaration in inProcess) return
inProcess.add(classLikeDeclaration) val supertypeRefs: List<FirResolvedTypeRef>
val supertypeComputationStatus = supertypeStatusMap[classLikeDecl]
require(supertypeComputationStatus is SupertypeComputationStatus.Computed) { supertypeRefs = if (supertypeComputationStatus != null) {
"Expected computed supertypes in breakLoops for ${classLikeDeclaration.symbol.classId}" require(supertypeComputationStatus is SupertypeComputationStatus.Computed) {
"Expected computed supertypes in breakLoops for ${classLikeDecl.symbol.classId}"
}
supertypeComputationStatus.supertypeRefs
} else {
when (classLikeDecl) {
is FirRegularClass ->
classLikeDecl.superTypeRefs.filterIsInstance<FirResolvedTypeRef>()
is FirTypeAlias ->
(classLikeDecl.expandedTypeRef as? FirResolvedTypeRef)?.let { listOf(it) } ?: listOf()
else -> return
}
} }
val typeRefs = supertypeComputationStatus.supertypeRefs if (classLikeDecl in visitedClassLikeDecls) {
val resultingTypeRefs = mutableListOf<FirResolvedTypeRef>() if (classLikeDecl in pathSet) {
var wereChanges = false loopedClassLikeDecls.add(classLikeDecl)
loopedClassLikeDecls.addAll(path.takeLastWhile { element -> element != classLikeDecl })
}
return
}
for (typeRef in typeRefs) { path.add(classLikeDecl)
val fir = typeRef.firClassLike(session) pathSet.add(classLikeDecl)
fir?.let(::dfs) visitedClassLikeDecls.add(classLikeDecl)
resultingTypeRefs.add(
if (fir in inProcess) { val parentId = classLikeDecl.symbol.classId.relativeClassName.parent()
wereChanges = true 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<FirResolvedTypeRef>()
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( createErrorTypeRef(
typeRef, supertypeRef,
"Loop in supertype: ${classLikeDeclaration.symbol.classId} -> ${fir?.symbol?.classId}" "Loop in supertype: ${classLikeDecl.symbol.classId} -> ${supertypeFir?.symbol?.classId}",
if (isTypeAlias) DiagnosticKind.RecursiveTypealiasExpansion else DiagnosticKind.LoopInSupertype
) )
} else } else {
typeRef supertypeRef
}
) )
} }
if (wereChanges) { if (isErrorInSupertypesFound) {
supertypeStatusMap[classLikeDeclaration] = SupertypeComputationStatus.Computed(resultingTypeRefs) supertypeStatusMap[classLikeDecl] = SupertypeComputationStatus.Computed(resultSupertypeRefs)
} }
inProcess.remove(classLikeDeclaration) path.removeAt(path.size - 1)
breakLoopsDfsVisited.add(classLikeDeclaration) pathSet.remove(classLikeDecl)
} }
for (classifier in newClassifiersForBreakingLoops) { for (classifier in newClassifiersForBreakingLoops) {
dfs(classifier) checkIsInLoop(classifier)
require(path.isEmpty()) {
"Path should be empty"
}
} }
newClassifiersForBreakingLoops.clear() newClassifiersForBreakingLoops.clear()
} }
@@ -36,6 +36,11 @@ enum class DiagnosticKind {
IllegalProjectionUsage, IllegalProjectionUsage,
MissingStdlibClass, MissingStdlibClass,
LoopInSupertype,
RecursiveTypealiasExpansion,
UnresolvedSupertype,
UnresolvedExpandedType,
IncorrectCharacterLiteral, IncorrectCharacterLiteral,
EmptyCharacterLiteral, EmptyCharacterLiteral,
TooManyCharactersInCharacterLiteral, TooManyCharactersInCharacterLiteral,
@@ -1,6 +1,6 @@
open class RecA<T>: RecB<T>() open class RecA<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecB<T><!>()
open class RecB<T>: <!OTHER_ERROR!>RecA<T><!>() open class RecB<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecA<T><!>()
open class SelfR<T>: <!OTHER_ERROR!>SelfR<T><!>() open class SelfR<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>SelfR<T><!>()
fun test(f: SelfR<String>) = f is RecA<String> fun test(f: SelfR<String>) = f is RecA<String>
fun test(f: RecB<String>) = f is RecA<String> fun test(f: RecB<String>) = f is RecA<String>
@@ -1,4 +0,0 @@
open class C : D() {
open class CC
}
open class D : C.CC()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class C : <!CYCLIC_INHERITANCE_HIERARCHY!>D<!>() { open class C : <!CYCLIC_INHERITANCE_HIERARCHY!>D<!>() {
open class CC open class CC
} }
@@ -1,3 +0,0 @@
open class E : E.EE() {
open class EE
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class E : <!CYCLIC_INHERITANCE_HIERARCHY!>E.EE<!>() { open class E : <!CYCLIC_INHERITANCE_HIERARCHY!>E.EE<!>() {
open class EE open class EE
} }
@@ -1,8 +0,0 @@
open class A : B()
open class B : <!OTHER_ERROR!>A<!>()
fun <T> select(vararg xs: T): T = xs[0]
fun foo() {
val x = select(A(), B(), "foo")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>() open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>()
open class B : <!CYCLIC_INHERITANCE_HIERARCHY!>A<!>() open class B : <!CYCLIC_INHERITANCE_HIERARCHY!>A<!>()
@@ -1,8 +0,0 @@
open class A : B()
open class B : <!OTHER_ERROR!>A<!>()
fun <T> select(vararg xs: T): T = xs[0]
fun foo() {
select(A(), B())
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>() open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>()
open class B : <!CYCLIC_INHERITANCE_HIERARCHY!>A<!>() open class B : <!CYCLIC_INHERITANCE_HIERARCHY!>A<!>()
@@ -1,30 +0,0 @@
interface A {
fun foo() {}
}
interface B : A, E {}
interface C : <!OTHER_ERROR!>B<!> {}
interface D : <!OTHER_ERROR!>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?.<!UNRESOLVED_REFERENCE!>foo<!>()
d?.<!UNRESOLVED_REFERENCE!>foo<!>()
e?.<!UNRESOLVED_REFERENCE!>foo<!>()
f?.<!UNRESOLVED_REFERENCE!>foo<!>()
g?.<!UNRESOLVED_REFERENCE!>foo<!>()
h?.<!UNRESOLVED_REFERENCE!>foo<!>()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface A { interface A {
fun foo() {} fun foo() {}
} }
@@ -1,17 +0,0 @@
// FILE: A.java
interface A extends C {
void foo();
}
// FILE: B.kt
interface B : <!EXPOSED_SUPER_INTERFACE!>A<!> {
fun bar()
}
// FILE: C.java
interface C extends B {
void baz();
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: A.java // FILE: A.java
interface A extends C { interface A extends C {
@@ -1,11 +0,0 @@
// FILE: J.java
class J extends K {
void foo() {}
}
// FILE: K.kt
class K : <!EXPOSED_SUPER_CLASS!>J<!>() {
fun bar() {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: J.java // FILE: J.java
class J extends K { class J extends K {
@@ -12,6 +12,6 @@ class J extends I {
// FILE: K.kt // FILE: K.kt
open class K : <!EXPOSED_SUPER_CLASS!>J<!>() { open class K : <!CYCLIC_INHERITANCE_HIERARCHY!>J<!>() {
fun baz() {} fun baz() {}
} }
@@ -5,7 +5,7 @@ interface ExceptionTracker : <!EXPOSED_SUPER_INTERFACE!>LockBasedStorageManager.
// FILE: StorageManager.kt // FILE: StorageManager.kt
interface StorageManager : ExceptionTracker { interface StorageManager : <!CYCLIC_INHERITANCE_HIERARCHY!>ExceptionTracker<!> {
fun foo() fun foo()
} }
@@ -1,10 +1,10 @@
// KT-303 Stack overflow on a cyclic class hierarchy // KT-303 Stack overflow on a cyclic class hierarchy
open class Foo() : Bar() { open class Foo() : <!CYCLIC_INHERITANCE_HIERARCHY!>Bar<!>() {
val a : Int = 1 val a : Int = 1
} }
open class Bar() : <!OTHER_ERROR!>Foo<!>() { open class Bar() : <!CYCLIC_INHERITANCE_HIERARCHY!>Foo<!>() {
} }
@@ -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
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// As in KT-18514 // As in KT-18514
object A : <!CYCLIC_INHERITANCE_HIERARCHY!>A.I<!> { object A : <!CYCLIC_INHERITANCE_HIERARCHY!>A.I<!> {
interface I interface I
@@ -1,6 +0,0 @@
open class A : B.BB() {
open class AA
}
open class B : A.AA() {
open class BB
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B.BB<!>() { open class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B.BB<!>() {
open class AA open class AA
} }
@@ -8,8 +8,8 @@ class Foo
class Bar class Bar
typealias YBar = <!OTHER_ERROR!>ZBar<!> typealias YBar = <!RECURSIVE_TYPEALIAS_EXPANSION!>ZBar<!>
typealias ZBar = YBar typealias ZBar = <!RECURSIVE_TYPEALIAS_EXPANSION!>YBar<!>
fun Foo.foo(body: Foo.() -> Unit) = body() fun Foo.foo(body: Foo.() -> Unit) = body()
fun Foo.zbar(body: ZBar.() -> Unit) = Bar().body() fun Foo.zbar(body: ZBar.() -> Unit) = Bar().body()
@@ -7,7 +7,7 @@ val bImpl: B.Companion.Interface
get() = null!! get() = null!!
interface A { interface A {
companion object : <!FINAL_SUPERTYPE!>Nested<!>(), Interface by aImpl, I<Nested, Interface> { companion object : <!CYCLIC_INHERITANCE_HIERARCHY!>Nested<!>(), <!CYCLIC_INHERITANCE_HIERARCHY!>Interface<!> by aImpl, <!CYCLIC_INHERITANCE_HIERARCHY!>I<Nested, Interface><!> {
class Nested class Nested
@@ -16,7 +16,7 @@ interface A {
} }
class B { class B {
companion object : <!FINAL_SUPERTYPE!>Nested<!>(), Interface by aImpl, I<Nested, Interface> { companion object : <!CYCLIC_INHERITANCE_HIERARCHY!>Nested<!>(), <!CYCLIC_INHERITANCE_HIERARCHY!>Interface<!> by aImpl, <!CYCLIC_INHERITANCE_HIERARCHY!>I<Nested, Interface><!> {
class Nested class Nested
@@ -1,7 +1,7 @@
class A : B() { class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>() {
open class Nested<T> open class Nested<T>
} }
typealias ANested<T> = A.Nested<T> typealias ANested<T> = <!RECURSIVE_TYPEALIAS_EXPANSION!>A.Nested<T><!>
open class B : ANested<Int>() open class B : <!CYCLIC_INHERITANCE_HIERARCHY, UNRESOLVED_REFERENCE!>ANested<Int><!>()
@@ -1,11 +1,12 @@
typealias R = <!OTHER_ERROR!>R<!> typealias R = <!RECURSIVE_TYPEALIAS_EXPANSION!>R<!>
typealias L = List<L> typealias L = <!RECURSIVE_TYPEALIAS_EXPANSION!>List<L><!>
typealias A = <!OTHER_ERROR!>B<!> typealias A = <!RECURSIVE_TYPEALIAS_EXPANSION!>B<!>
typealias B = A typealias B = <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!>
typealias F1 = (Int) -> F2 typealias F1 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(Int) -> F2<!>
typealias F2 = (F1) -> Int typealias F2 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(F1) -> Int<!>
typealias F3 = (F1) -> Int
val x: A = TODO() val x: F3 = TODO()
+2 -1
View File
@@ -7,5 +7,6 @@ typealias B = <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!>
typealias F1 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(Int) -> F2<!> typealias F1 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(Int) -> F2<!>
typealias F2 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(F1) -> Int<!> typealias F2 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(F1) -> Int<!>
typealias F3 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(F1) -> Int<!>
val x: <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!> = TODO() val x: <!RECURSIVE_TYPEALIAS_EXPANSION!>F3<!> = TODO()
@@ -1,9 +1,11 @@
package 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 A = B
public typealias B = A public typealias B = A
public typealias F1 = (kotlin.Int) -> F2 public typealias F1 = (kotlin.Int) -> F2
public typealias F2 = (F1) -> kotlin.Int public typealias F2 = (F1) -> kotlin.Int
public typealias F3 = (F1) -> kotlin.Int
public typealias L = kotlin.collections.List<L> public typealias L = kotlin.collections.List<L>
public typealias R = R public typealias R = R
@@ -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
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>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
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class A<!>() : Case2Base() {
}
}
// TESTCASE NUMBER: 3
fun case3() {
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>object<!> : CaseOuter.CaseBase() {}.outerFoo()
}
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class B<!>() : CaseOuter.CaseBase() {}
sealed class CaseOuter {
val v = "v"
abstract fun outerFoo();
abstract class CaseBase() : CaseOuter() {
abstract fun foo(): String
}
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class A<!>() : CaseBase() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +NewInference +ProhibitInvisibleAbstractMethodsInSuperclasses // !LANGUAGE: +NewInference +ProhibitInvisibleAbstractMethodsInSuperclasses
// !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION
// SKIP_TXT // SKIP_TXT
@@ -407,6 +407,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.CYCLIC_INHERITANCE_HIERARCHY) { firDiagnostic ->
CyclicInheritanceHierarchyImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic -> add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic ->
ConstructorInObjectImpl( ConstructorInObjectImpl(
firDiagnostic as FirPsiDiagnostic<*>, firDiagnostic as FirPsiDiagnostic<*>,
@@ -2378,6 +2384,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.RECURSIVE_TYPEALIAS_EXPANSION) { firDiagnostic ->
RecursiveTypealiasExpansionImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.REDUNDANT_VISIBILITY_MODIFIER) { firDiagnostic -> add(FirErrors.REDUNDANT_VISIBILITY_MODIFIER) { firDiagnostic ->
RedundantVisibilityModifierImpl( RedundantVisibilityModifierImpl(
firDiagnostic as FirPsiDiagnostic<*>, firDiagnostic as FirPsiDiagnostic<*>,
@@ -303,6 +303,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val reason: String abstract val reason: String
} }
abstract class CyclicInheritanceHierarchy : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = CyclicInheritanceHierarchy::class
}
abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() { abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = ConstructorInObject::class override val diagnosticClass get() = ConstructorInObject::class
} }
@@ -1670,6 +1674,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ToplevelTypealiasesOnly::class override val diagnosticClass get() = ToplevelTypealiasesOnly::class
} }
abstract class RecursiveTypealiasExpansion : KtFirDiagnostic<KtTypeAlias>() {
override val diagnosticClass get() = RecursiveTypealiasExpansion::class
}
abstract class RedundantVisibilityModifier : KtFirDiagnostic<KtModifierListOwner>() { abstract class RedundantVisibilityModifier : KtFirDiagnostic<KtModifierListOwner>() {
override val diagnosticClass get() = RedundantVisibilityModifier::class override val diagnosticClass get() = RedundantVisibilityModifier::class
} }
@@ -472,6 +472,13 @@ internal class SupertypeNotAClassOrInterfaceImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
} }
internal class CyclicInheritanceHierarchyImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.CyclicInheritanceHierarchy(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ConstructorInObjectImpl( internal class ConstructorInObjectImpl(
firDiagnostic: FirPsiDiagnostic<*>, firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken, override val token: ValidityToken,
@@ -2703,6 +2710,13 @@ internal class ToplevelTypealiasesOnlyImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
} }
internal class RecursiveTypealiasExpansionImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.RecursiveTypealiasExpansion(), KtAbstractFirDiagnostic<KtTypeAlias> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class RedundantVisibilityModifierImpl( internal class RedundantVisibilityModifierImpl(
firDiagnostic: FirPsiDiagnostic<*>, firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken, override val token: ValidityToken,
+5 -5
View File
@@ -1,11 +1,11 @@
interface A { interface A {
fun foo() {} fun foo() {}
} }
interface B : A, E {} interface B : A, <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">E</error> {}
interface C : <error descr="[OTHER_ERROR] Unknown (other) error">B</error> {} interface C : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">B</error> {}
interface D : <error descr="[OTHER_ERROR] Unknown (other) error">B</error> {} interface D : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">B</error> {}
interface E : F {} interface E : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">F</error> {}
interface F : D, C {} interface F : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">D</error>, <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">C</error> {}
interface G : F {} interface G : F {}
interface H : F {} interface H : F {}
+2 -2
View File
@@ -1,10 +1,10 @@
// KT-303 Stack overflow on a cyclic class hierarchy // KT-303 Stack overflow on a cyclic class hierarchy
open class Foo() : Bar() { open class Foo() : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">Bar</error>() {
val a : Int = 1 val a : Int = 1
} }
open class Bar() : <error descr="[OTHER_ERROR] Unknown (other) error">Foo</error>() { open class Bar() : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">Foo</error>() {
} }
+1 -1
View File
@@ -1,3 +1,3 @@
class A : <error descr="[OTHER_ERROR] Unknown (other) error">A</error>() {} class A : <error descr="[CYCLIC_INHERITANCE_HIERARCHY] There's a cycle in the inheritance hierarchy for this type">A</error>() {}
val x : Int = <error descr="[INITIALIZER_TYPE_MISMATCH] Initializer type mismatch: expected kotlin/Int, actual A"><error descr="[TYPE_MISMATCH] Type mismatch: inferred type is A but kotlin/Int was expected">A()</error></error> val x : Int = <error descr="[INITIALIZER_TYPE_MISMATCH] Initializer type mismatch: expected kotlin/Int, actual A"><error descr="[TYPE_MISMATCH] Type mismatch: inferred type is A but kotlin/Int was expected">A()</error></error>