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 058470f0584..444740ffba4 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 @@ -140,6 +140,16 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("type") } val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error(PositioningStrategy.VARIANCE_MODIFIER) + val INCONSISTENT_TYPE_PARAMETER_VALUES by error(PositioningStrategy.SUPERTYPES_LIST) { + parameter("typeParameter") + parameter("type") + parameter>("bounds") + } + val INCONSISTENT_TYPE_PARAMETER_BOUNDS by error { + parameter("typeParameter") + parameter("type") + parameter>("bounds") + } } val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") { 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 f41dc5d0149..86b1996e475 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 @@ -146,6 +146,8 @@ object FirErrors { val CYCLIC_INHERITANCE_HIERARCHY by error0() val EXPANDED_TYPE_CANNOT_BE_INHERITED by error1() val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0(SourceElementPositioningStrategies.VARIANCE_MODIFIER) + val INCONSISTENT_TYPE_PARAMETER_VALUES by error3>(SourceElementPositioningStrategies.SUPERTYPES_LIST) + val INCONSISTENT_TYPE_PARAMETER_BOUNDS by error3>() // Constructor problems val CONSTRUCTOR_IN_OBJECT by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirInconsistentTypeParameterHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirInconsistentTypeParameterHelpers.kt new file mode 100644 index 00000000000..1f21e7f2fb0 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirInconsistentTypeParameterHelpers.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers + +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.types.AbstractTypeChecker + +fun checkInconsistentTypeParameters( + firTypeRefClasses: List>, + context: CheckerContext, + reporter: DiagnosticReporter, + source: FirSourceElement?, + isValues: Boolean +) { + val result = buildDeepSubstitutionMultimap(firTypeRefClasses, context) + for ((typeParameterSymbol, typeAndProjections) in result) { + val projections = typeAndProjections.projections + if (projections.size > 1) { + if (isValues) { + reporter.reportOn( + source, + FirErrors.INCONSISTENT_TYPE_PARAMETER_VALUES, + typeParameterSymbol, + typeAndProjections.classSymbol, + projections, + context + ) + } else { + reporter.reportOn( + source, + FirErrors.INCONSISTENT_TYPE_PARAMETER_BOUNDS, + typeParameterSymbol, + typeAndProjections.classSymbol, + projections, + context + ) + } + } + } +} + +private fun buildDeepSubstitutionMultimap( + firTypeRefClasses: List>, + context: CheckerContext, +): Map { + val result = mutableMapOf() + val substitution = mutableMapOf() + val session = context.session + val typeContext = session.typeContext + + fun fillInDeepSubstitutor(typeArguments: Array?, firClass: FirRegularClass) { + if (typeArguments != null) { + val typeParameters = firClass.typeParameters + val count = minOf(typeArguments.size, typeParameters.size) + + for (index in 0 until count) { + val typeArgument = typeArguments[index] + + val substitutedArgument = ConeSubstitutorByMap(substitution, session).substituteArgument(typeArgument) ?: typeArgument + val substitutedType = substitutedArgument.type ?: continue + + val typeParameterSymbol = typeParameters[index].symbol + + substitution[typeParameterSymbol] = substitutedType + var classSymbolAndProjections = result[typeParameterSymbol] + val projections: MutableList + if (classSymbolAndProjections == null) { + projections = mutableListOf() + classSymbolAndProjections = ClassSymbolAndProjections(firClass.symbol, projections) + result[typeParameterSymbol] = classSymbolAndProjections + } else { + projections = classSymbolAndProjections.projections + } + + if (projections.all { + it != substitutedType && !AbstractTypeChecker.equalTypes(typeContext, it, substitutedType) + }) { + projections.add(substitutedType) + } + } + } + + for (superTypeRef in firClass.superTypeRefs) { + withSuppressedDiagnostics(superTypeRef, context) { + val fullyExpandedType = superTypeRef.coneType.fullyExpandedType(session) + val superTypeClass = fullyExpandedType.toRegularClass(session) + if (!fullyExpandedType.isEnum && superTypeClass != null) { + fillInDeepSubstitutor(fullyExpandedType.typeArguments, superTypeClass) + } + } + } + } + + for (firTypeRefClass in firTypeRefClasses) { + fillInDeepSubstitutor(firTypeRefClass.first?.coneType?.fullyExpandedType(session)?.typeArguments, firTypeRefClass.second) + } + return result +} + +private data class ClassSymbolAndProjections( + val classSymbol: FirRegularClassSymbol, + val projections: MutableList +) \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt index 1d480ad3c7c..dab2b850731 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypesChecker.kt @@ -7,9 +7,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.fir.analysis.checkers.* +import org.jetbrains.kotlin.fir.analysis.checkers.checkInconsistentTypeParameters import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument +import org.jetbrains.kotlin.fir.analysis.checkers.isConflictingOrNotInvariant import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -21,7 +22,6 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirSupertypesChecker : FirClassChecker() { @@ -108,5 +108,9 @@ object FirSupertypesChecker : FirClassChecker() { } } } + + if (declaration is FirRegularClass && declaration.superTypeRefs.size > 1) { + checkInconsistentTypeParameters(listOf(Pair(null, declaration)), context, reporter, declaration.source, true) + } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt index 26eebf9e2d6..9e51dfbc26f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt @@ -42,6 +42,7 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { checkConflictingBounds(declaration, context, reporter) checkTypeAliasBound(declaration, containingDeclaration, context, reporter) checkDynamicBounds(declaration, context, reporter) + checkInconsistentTypeParameterBounds(declaration, context, reporter) } private fun checkFinalUpperBounds( @@ -89,7 +90,7 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { // report the diagnostic on that bound //take TypeConstraint bounds only to report on the same point as old FE - val constraintBounds = with(SourceNavigator.forElement(declaration)){ + val constraintBounds = with(SourceNavigator.forElement(declaration)) { bounds.filter { it.isInTypeConstraint() }.toSet() } val reportOn = @@ -154,5 +155,29 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { private fun KotlinTypeMarker.isRelated(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean = isSubtypeOf(context, type) || isSupertypeOf(context, type) + private fun checkInconsistentTypeParameterBounds( + declaration: FirTypeParameter, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + if (declaration.bounds.size <= 1) return + val firTypeRefClasses = mutableListOf>() + val firRegularClassesSet = mutableSetOf() + + for (bound in declaration.bounds) { + val firRegularClass = bound.toRegularClass(context.session) + if (firRegularClassesSet.contains(firRegularClass)) { + // no need to throw INCONSISTENT_TYPE_PARAMETER_BOUNDS diagnostics here because REPEATED_BOUNDS diagnostic is already exist + return + } + + if (firRegularClass != null) { + firRegularClassesSet.add(firRegularClass) + firTypeRefClasses.add(Pair(bound, firRegularClass)) + } + } + + checkInconsistentTypeParameters(firTypeRefClasses, context, reporter, declaration.source, false) + } } 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 3b4b87d5dd9..21f2de51d0f 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 @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.REND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VARIABLE_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY @@ -171,6 +172,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_ENUM import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_TYPES_WARNING +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCONSISTENT_TYPE_PARAMETER_BOUNDS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCONSISTENT_TYPE_PARAMETER_VALUES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFIX_MODIFIER_REQUIRED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION @@ -466,6 +469,20 @@ class FirDefaultErrorMessages { RENDER_TYPE ) map.put(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, "Projections are not allowed for immediate arguments of a supertype") + map.put( + INCONSISTENT_TYPE_PARAMETER_VALUES, + "Type parameter {0} of ''{1}'' has inconsistent values: {2}", + SYMBOL, + SYMBOL, + RENDER_COLLECTION_OF_TYPES + ) + map.put( + INCONSISTENT_TYPE_PARAMETER_BOUNDS, + "Type parameter {0} of ''{1}'' has inconsistent bounds: {2}", + SYMBOL, + SYMBOL, + RENDER_COLLECTION_OF_TYPES + ) // Constructor problems map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index 7b65f23e562..9eac0190297 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -38,6 +38,12 @@ object FirDiagnosticRenderers { } } + val RENDER_COLLECTION_OF_TYPES = Renderer { types: Collection -> + types.joinToString(separator = ", ") { type -> + RENDER_TYPE.render(type) + } + } + val TO_STRING = Renderer { element: Any? -> element.toString() } diff --git a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.fir.kt b/compiler/testData/diagnostics/tests/GenericArgumentConsistency.fir.kt deleted file mode 100644 index 2d50e8c8fd3..00000000000 --- a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.fir.kt +++ /dev/null @@ -1,43 +0,0 @@ -// FILE: a.kt -interface A {} -interface B : A {} -interface C : B, A {} -interface C1 : B, A {} -interface D : C, B{} - -interface A1 {} -interface B1 : A1 {} -interface B2 : A1, B1 {} - -interface BA1 {} -interface BB1 : BA1 {} -interface BB2 : BA1, BB1 {} - - -// FILE: b.kt -package x - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} - -// FILE: c.kt -package x2 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} - -// FILE: d.kt -package x3 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} - -// FILE: e.kt -package sx2 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} diff --git a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.kt b/compiler/testData/diagnostics/tests/GenericArgumentConsistency.kt index a9c4557b742..bb5d98915e5 100644 --- a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.kt +++ b/compiler/testData/diagnostics/tests/GenericArgumentConsistency.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: a.kt interface A {} interface B : A {} @@ -16,28 +17,36 @@ interface BB2 : BA1, BB1 {} // FILE: b.kt package x - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} +interface AA1 {} +interface AB1 : AA1 {} +interface AB3 : AA1> {} +interface AB2 : AA1, AB1, AB3 {} // FILE: c.kt package x2 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} +interface AA1 {} +interface AB1 : AA1 {} +interface AB3 : AA1> {} +interface AB2 : AA1, AB1, AB3 {} // FILE: d.kt package x3 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} +interface AA1 {} +interface AB1 : AA1 {} +interface AB3 : AA1> {} +interface AB2 : AA1, AB1, AB3 {} // FILE: e.kt package sx2 - interface AA1 {} - interface AB1 : AA1 {} - interface AB3 : AA1> {} - interface AB2 : AA1, AB1, AB3 {} +interface AA1 {} +interface AB1 : AA1 {} +interface AB3 : AA1> {} +interface AB2 : AA1, AB1, AB3 {} + +// FILE: f.kt +interface I0 +abstract class C2 : I0 +typealias TA = C2 +interface I2 +interface I3 +class C3 : TA(), I0 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.txt b/compiler/testData/diagnostics/tests/GenericArgumentConsistency.txt index 87581f389ea..262b2c79f62 100644 --- a/compiler/testData/diagnostics/tests/GenericArgumentConsistency.txt +++ b/compiler/testData/diagnostics/tests/GenericArgumentConsistency.txt @@ -60,12 +60,45 @@ public interface C1 : B, A { public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String } +public abstract class C2 : I0 { + public constructor C2() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C3 : TA /* = C2 */, I0 { + public constructor C3() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + public interface D : C, B { public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String } +public interface I0 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I2 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I3 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public typealias TA = C2 + package sx2 { public interface AA1 { @@ -173,3 +206,4 @@ package x3 { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } } + diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.fir.kt b/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.fir.kt deleted file mode 100644 index f69dc7a1aaf..00000000000 --- a/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -interface A -interface B: A -interface D - -interface BaseSuper -interface BaseImpl: BaseSuper -interface DerivedSuper: BaseSuper, BaseImpl - -fun test(t: BaseSuper) = t is DerivedSuper \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.kt b/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.kt index 296ae7582aa..2fe07a78dc0 100644 --- a/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.kt +++ b/compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface A interface B: A interface D diff --git a/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.fir.kt b/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.fir.kt deleted file mode 100644 index e6f3a6df42c..00000000000 --- a/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -interface A -interface B : A - -interface ListA : List -interface ListB : List - -interface Z where T : ListA, T : ListB diff --git a/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.kt b/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.kt index 71dc57aa668..74e687e8307 100644 --- a/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.kt +++ b/compiler/testData/diagnostics/tests/generics/InconsistentTypeParameterBounds.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface A interface B : A diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.fir.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.fir.kt deleted file mode 100644 index c8b6efc9e1d..00000000000 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.fir.kt +++ /dev/null @@ -1,33 +0,0 @@ -interface IA { - fun method(): String - val propVal: String - var propVar: String -} - -interface IB1 : IA -interface IB2 : IA - -interface IGA { - fun method(): T - val propVal: T - var propVar: T -} - -interface IGB1Str : IGA -interface IGB2Str : IGA -interface IGB3Int : IGA - -interface IGB4T : IGA -interface IGB5T : IGA - -interface IC : IB1, IB2 - -interface IGC1 : IGB1Str, IGB2Str - -interface IGC2 : IGB1Str, IGB3Int - -interface IGC3 : IGB4T, IGB5T - -interface IGC4 : IGB4T, IGB5T - -interface IGC5 : IGB4T, IGB5T \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.kt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.kt index 3e6fb0ded2b..5002e80f382 100644 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.kt +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/unrelatedInherited.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface IA { fun method(): String val propVal: String diff --git a/compiler/testData/diagnostics/tests/subtyping/findClosestCorrespondingSupertype.fir.kt b/compiler/testData/diagnostics/tests/subtyping/findClosestCorrespondingSupertype.fir.kt index f42d97e3c21..be4c844abff 100644 --- a/compiler/testData/diagnostics/tests/subtyping/findClosestCorrespondingSupertype.fir.kt +++ b/compiler/testData/diagnostics/tests/subtyping/findClosestCorrespondingSupertype.fir.kt @@ -2,7 +2,7 @@ interface X interface A: X -interface B : A, X +interface B : A, X fun foo(x: B) { // Checks that when checking subtypes we search closes corresponding constructor (e.g. with BFS) 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 70b84fd9950..a750799be59 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 @@ -425,6 +425,28 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INCONSISTENT_TYPE_PARAMETER_VALUES) { firDiagnostic -> + InconsistentTypeParameterValuesImpl( + firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir), + firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.b.fir), + firDiagnostic.c.map { coneKotlinType -> + firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType) + }, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirErrors.INCONSISTENT_TYPE_PARAMETER_BOUNDS) { firDiagnostic -> + InconsistentTypeParameterBoundsImpl( + firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir), + firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.b.fir), + firDiagnostic.c.map { coneKotlinType -> + firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType) + }, + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic -> ConstructorInObjectImpl( 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 ed7c8c5bf0a..2490e85ef8b 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 @@ -316,6 +316,20 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ProjectionInImmediateArgumentToSupertype::class } + abstract class InconsistentTypeParameterValues : KtFirDiagnostic() { + override val diagnosticClass get() = InconsistentTypeParameterValues::class + abstract val typeParameter: KtTypeParameterSymbol + abstract val type: KtClassLikeSymbol + abstract val bounds: List + } + + abstract class InconsistentTypeParameterBounds : KtFirDiagnostic() { + override val diagnosticClass get() = InconsistentTypeParameterBounds::class + abstract val typeParameter: KtTypeParameterSymbol + abstract val type: KtClassLikeSymbol + abstract val bounds: List + } + abstract class ConstructorInObject : KtFirDiagnostic() { override val diagnosticClass get() = ConstructorInObject::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 5cda196cd7a..4413bf62ab9 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 @@ -494,6 +494,26 @@ internal class ProjectionInImmediateArgumentToSupertypeImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class InconsistentTypeParameterValuesImpl( + override val typeParameter: KtTypeParameterSymbol, + override val type: KtClassLikeSymbol, + override val bounds: List, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InconsistentTypeParameterValues(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + +internal class InconsistentTypeParameterBoundsImpl( + override val typeParameter: KtTypeParameterSymbol, + override val type: KtClassLikeSymbol, + override val bounds: List, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InconsistentTypeParameterBounds(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class ConstructorInObjectImpl( firDiagnostic: FirPsiDiagnostic, override val token: ValidityToken, diff --git a/idea/testData/checker/GenericArgumentConsistency.fir.kt b/idea/testData/checker/GenericArgumentConsistency.fir.kt index 2658e33e8c8..edd786620ca 100644 --- a/idea/testData/checker/GenericArgumentConsistency.fir.kt +++ b/idea/testData/checker/GenericArgumentConsistency.fir.kt @@ -1,42 +1,42 @@ interface A {} interface B : A {} -interface C : B, A {} -interface C1 : B, A {} -interface D : C, B{} +interface C : B, A {} +interface C1 : B, A {} +interface D : C, B{} interface A1 {} interface B1 : A1 {} -interface B2 : A1, B1 {} +interface B2 : A1, B1 {} interface BA1 {} interface BB1 : BA1 {} -interface BB2 : BA1, BB1 {} +interface BB2 : BA1, BB1 {} //package x { interface xAA1 {} interface xAB1 : xAA1 {} interface xAB3 : xAA1> {} - interface xAB2 : xAA1, xAB1, xAB3 {} + interface xAB2 : xAA1, xAB1, xAB3 {} //} //package x2 { interface x2AA1 {} interface x2AB1 : x2AA1 {} interface x2AB3 : x2AA1> {} - interface x2AB2 : x2AA1, x2AB1, x2AB3 {} + interface x2AB2 : x2AA1, x2AB1, x2AB3 {} //} //package x3 { interface x3AA1 {} interface x3AB1 : x3AA1 {} interface x3AB3 : x3AA1> {} - interface x3AB2 : x3AA1, x3AB1, x3AB3 {} + interface x3AB2 : x3AA1, x3AB1, x3AB3 {} //} //package sx2 { interface sx2AA1 {} interface sx2AB1 : sx2AA1 {} interface sx2AB3 : sx2AA1> {} - interface sx2AB2 : sx2AA1, sx2AB1, sx2AB3 {} + interface sx2AB2 : sx2AA1, sx2AB1, sx2AB3 {} //}