[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:
committed by
teamcityserver
parent
d1531f9cdd
commit
c4c2fbb5a0
+1
-1
@@ -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
-1
@@ -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|>()
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -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<!>()
|
||||||
|
|||||||
+2
-1
@@ -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)
|
||||||
|
|||||||
+2
-5
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -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")
|
||||||
|
|||||||
+7
-3
@@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+104
-40
@@ -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>
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
open class C : D() {
|
|
||||||
open class CC
|
|
||||||
}
|
|
||||||
open class D : C.CC()
|
|
||||||
+1
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
-3
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-8
@@ -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")
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -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<!>()
|
||||||
|
|
||||||
|
|||||||
-8
@@ -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
@@ -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() {}
|
||||||
}
|
}
|
||||||
|
|||||||
-17
@@ -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 {
|
||||||
|
|||||||
+1
-1
@@ -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() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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<!>() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-22
@@ -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
|
||||||
|
|||||||
-6
@@ -1,6 +0,0 @@
|
|||||||
open class A : B.BB() {
|
|
||||||
open class AA
|
|
||||||
}
|
|
||||||
open class B : A.AA() {
|
|
||||||
open class BB
|
|
||||||
}
|
|
||||||
+1
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -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()
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
-51
@@ -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
@@ -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
|
||||||
|
|||||||
+12
@@ -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<*>,
|
||||||
|
|||||||
+8
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user