diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt index e67fcfbbe9d..417164e90f4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt @@ -38,15 +38,15 @@ fun test(z: Int, c: Char) {} typealias BA = A -fun kek(t: T) where T : (String) -> Any?, T : Char {} -fun kek(t: T) where T : () -> Boolean, T : String {} +fun <T> kek(t: T) where T : (String) -> Any?, T : Char {} +fun <T> kek(t: T) where T : () -> Boolean, T : String {} fun Int> kek(t: T) {} fun lol(a: Array) {} fun lol(a: Array) {} -fun mem(t: T) where T : () -> Boolean, T : String {} -fun mem(t: T) where T : String, T : () -> Boolean {} +fun <T> mem(t: T) where T : () -> Boolean, T : String {} +fun <T> mem(t: T) where T : String, T : () -> Boolean {} class M { companion object {} 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 b4c7e1c91d1..e17da9a11f5 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 @@ -294,15 +294,21 @@ object DIAGNOSTICS_LIST : DiagnosticList() { parameter("typeParameter") } - val FINAL_UPPER_BOUND by warning { + val FINAL_UPPER_BOUND by warning { parameter("type") } - val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error() + val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error() - val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error() + val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error() - val ONLY_ONE_CLASS_BOUND_ALLOWED by error() + val ONLY_ONE_CLASS_BOUND_ALLOWED by error() + + val REPEATED_BOUND by error() + + val CONFLICTING_UPPER_BOUNDS by error { + parameter("typeParameter") + } } val REFLECTION by object : DiagnosticGroup("Reflection") { 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 94d4c12323e..7f43601add9 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 @@ -220,10 +220,12 @@ object FirErrors { val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0(SourceElementPositioningStrategies.DECLARATION_NAME) val KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE by error1(SourceElementPositioningStrategies.DECLARATION_NAME) val TYPE_PARAMETER_AS_REIFIED by error1() - val FINAL_UPPER_BOUND by warning1() - val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error0() - val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error0() - val ONLY_ONE_CLASS_BOUND_ALLOWED by error0() + val FINAL_UPPER_BOUND by warning1() + val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error0() + val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error0() + val ONLY_ONE_CLASS_BOUND_ALLOWED by error0() + val REPEATED_BOUND by error0() + val CONFLICTING_UPPER_BOUNDS by error1() // Reflection val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) 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 c9aa2c6c1cc..b489be2f633 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 @@ -7,18 +7,16 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.fir.analysis.checkers.canHaveSubtypes +import org.jetbrains.kotlin.fir.analysis.checkers.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.isInlineOnly -import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass 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.declarations.* -import org.jetbrains.kotlin.fir.types.ConeTypeParameterType -import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.isExtensionFunctionType +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { @@ -48,7 +46,8 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { checkOnlyOneTypeParameterBound(declaration, context, reporter) } - checkOnlyOneClassBound(declaration, context, reporter) + checkBoundUniqueness(declaration, context, reporter) + checkConflictingBounds(declaration, context, reporter) } private fun checkOnlyOneTypeParameterBound(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { @@ -78,15 +77,47 @@ object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { } - private fun checkOnlyOneClassBound(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { + private fun checkBoundUniqueness(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { val seenClasses = mutableSetOf() - val bounds = declaration.bounds.distinctBy { it.coneType } - bounds.forEach { bound -> + val allNonErrorBounds = declaration.bounds.filter { it !is FirErrorTypeRef } + val uniqueBounds = allNonErrorBounds.distinctBy { it.coneType.classId ?: it.coneType } + + uniqueBounds.forEach { bound -> bound.coneType.toRegularClass(context.session)?.let { clazz -> if (classKinds.contains(clazz.classKind) && seenClasses.add(clazz) && seenClasses.size > 1) { reporter.reportOn(bound.source, FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED, context) } } } + + allNonErrorBounds.minus(uniqueBounds).forEach { bound -> + reporter.reportOn(bound.source, FirErrors.REPEATED_BOUND, context) + } } + + private fun checkConflictingBounds(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration.bounds.size < 2) return + + fun anyConflictingTypes(types: List): Boolean { + types.forEach { type -> + if (!type.canHaveSubtypes(context.session)) { + types.forEach { otherType -> + if (type != otherType && !type.isRelated(context.session.typeContext, otherType)){ + return true + } + } + } + } + return false + } + + if (anyConflictingTypes(declaration.bounds.map { it.coneType })) { + reporter.reportOn(declaration.source, FirErrors.CONFLICTING_UPPER_BOUNDS, declaration.symbol, context) + } + } + + private fun KotlinTypeMarker.isRelated(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean = + isSubtypeOf(context, type) || isSupertypeOf(context, type) + + } 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 66e15f5e6f7..ea45b52a744 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 @@ -58,6 +58,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTIO import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_ON_NULLABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_UPPER_BOUNDS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_OBJECT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL @@ -184,6 +185,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SETTER_ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_VISIBILITY_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY @@ -457,7 +459,14 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { "Type parameter cannot have any other bounds if it's bounded by another type parameter" ) - map.put(ONLY_ONE_CLASS_BOUND_ALLOWED,"Only one of the upper bounds can be a class") + map.put(ONLY_ONE_CLASS_BOUND_ALLOWED, "Only one of the upper bounds can be a class") + map.put(REPEATED_BOUND, "Type parameter already has this bound") + + map.put( + CONFLICTING_UPPER_BOUNDS, + "Upper bounds of {0} have empty intersection", + SYMBOL + ) // Reflection map.put( diff --git a/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt b/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt index d0eb0603037..936c0609d51 100644 --- a/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt +++ b/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt @@ -48,7 +48,7 @@ class BarFoo> class Buzz where T : Bar, T : nioho class XFoo> -class Y where T : Foo, T : Bar +class Y<T> where T : Foo, T : Bar fun test2(t : T) where diff --git a/compiler/testData/diagnostics/tests/generics/TypeParameterBounds.fir.kt b/compiler/testData/diagnostics/tests/generics/TypeParameterBounds.fir.kt index 3612db3e2f2..25f91dbcf10 100644 --- a/compiler/testData/diagnostics/tests/generics/TypeParameterBounds.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/TypeParameterBounds.fir.kt @@ -6,18 +6,18 @@ interface B interface D -interface IncorrectF> where T : D +interface IncorrectF> where T : D -interface CorrectF where T : D, T : D +interface CorrectF where T : D, T : D interface G -interface IncorrectH>> where T : G> +interface IncorrectH>> where T : G> -interface CorrectH where T : G>, T : G> +interface CorrectH where T : G>, T : G> -interface incorrectJ>> where T : G> +interface incorrectJ>> where T : G> -interface correctJ where T : G>, T : G> +interface correctJ where T : G>, T : G> -fun bar() where T : D, T : D {} +fun bar() where T : D, T : D {} diff --git a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.fir.kt b/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.fir.kt deleted file mode 100644 index 5dbe80868f8..00000000000 --- a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -interface I1 -interface I2 -open class C - -interface A1 where V : K, V : K -interface A2 where W : K, W : V -interface A3V> where V : I1, V : K, V : I2 -interface A4<K, V> where K : I1, K : I2, K : C, K : V, V : I2, V : I1 - -fun f1() where V : K, V : K {} -fun f2() where W : K, W : V { - fun f3() where T : K, T : V {} - fun f4() where T : K, T : K {} -} -fun W> f3() where W : K, W : V, W : Any {} diff --git a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt b/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt index 32eafa745cf..043541acb9d 100644 --- a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt +++ b/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface I1 interface I2 open class C diff --git a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt deleted file mode 100644 index 520ebe9ab1d..00000000000 --- a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -open class C1 -open class C2 -open class C3 : C2() - -class A1 where T : C1, T : C2 -class A2 where T : C1, T : C2, T : C3 -class A3 where T : C2, T : C3 -class A4 where T : C3, T : C2 - -fun f1() where T : C1, T : C2, T : C3 {} -fun f2() where T : C2, T : C3 {} -fun f3() where T : C3, T : C2 {} - -enum class E1 -class A5 where T : C1, T : E1 - -object O1 -class A6 where T : O1, T : C2 diff --git a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.kt b/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.kt index fcf7bee4652..fb8b8ddb7cb 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class C1 open class C2 open class C3 : C2() diff --git a/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.fir.kt deleted file mode 100644 index 9364f6ab3c1..00000000000 --- a/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -interface I1 - -class A1 where T : I1, T : I1 -class A2 where T : I1, T : I1? -class A3 where K : V, K : V - -fun f1() where T : I1, T : I1 {} diff --git a/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt b/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt index 960c7c0a2ae..c73aa424ca8 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface I1 class A1 where T : I1, T : I1 diff --git a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt index 4b2f3531770..d7986f1b23e 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt @@ -1,6 +1,6 @@ fun > f1() {} fun > f2() {} -fun f3() where A : Array, A : Array {} +fun f3() where A : Array, A : Array {} fun IntArray> f4() {} @@ -9,7 +9,7 @@ fun f5() where T : Array {} val > T.v: String get() = "" class C2> -interface C3 where A : Array, A : Array +interface C3 where A : Array, A : Array fun foo() { class C1> { 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 d52f35c5d24..e0680a22a23 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 @@ -932,6 +932,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.REPEATED_BOUND) { firDiagnostic -> + RepeatedBoundImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.CONFLICTING_UPPER_BOUNDS) { firDiagnostic -> + ConflictingUpperBoundsImpl( + firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir), + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic -> ExtensionInClassReferenceNotAllowedImpl( firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), 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 842e03a35a6..910234cba52 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 @@ -647,23 +647,32 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val typeParameter: KtTypeParameterSymbol } - abstract class FinalUpperBound : KtFirDiagnostic() { + abstract class FinalUpperBound : KtFirDiagnostic() { override val diagnosticClass get() = FinalUpperBound::class abstract val type: KtType } - abstract class UpperBoundIsExtensionFunctionType : KtFirDiagnostic() { + abstract class UpperBoundIsExtensionFunctionType : KtFirDiagnostic() { override val diagnosticClass get() = UpperBoundIsExtensionFunctionType::class } - abstract class BoundsNotAllowedIfBoundedByTypeParameter : KtFirDiagnostic() { + abstract class BoundsNotAllowedIfBoundedByTypeParameter : KtFirDiagnostic() { override val diagnosticClass get() = BoundsNotAllowedIfBoundedByTypeParameter::class } - abstract class OnlyOneClassBoundAllowed : KtFirDiagnostic() { + abstract class OnlyOneClassBoundAllowed : KtFirDiagnostic() { override val diagnosticClass get() = OnlyOneClassBoundAllowed::class } + abstract class RepeatedBound : KtFirDiagnostic() { + override val diagnosticClass get() = RepeatedBound::class + } + + abstract class ConflictingUpperBounds : KtFirDiagnostic() { + override val diagnosticClass get() = ConflictingUpperBounds::class + abstract val typeParameter: KtTypeParameterSymbol + } + abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic() { override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class abstract val referencedDeclaration: KtCallableSymbol 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 ef0328344d3..94abfe7054a 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 @@ -1045,28 +1045,43 @@ internal class FinalUpperBoundImpl( override val type: KtType, firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.FinalUpperBound(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.FinalUpperBound(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } internal class UpperBoundIsExtensionFunctionTypeImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.UpperBoundIsExtensionFunctionType(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.UpperBoundIsExtensionFunctionType(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } internal class BoundsNotAllowedIfBoundedByTypeParameterImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.BoundsNotAllowedIfBoundedByTypeParameter(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.BoundsNotAllowedIfBoundedByTypeParameter(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } internal class OnlyOneClassBoundAllowedImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.OnlyOneClassBoundAllowed(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.OnlyOneClassBoundAllowed(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class RepeatedBoundImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.RepeatedBound(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class ConflictingUpperBoundsImpl( + override val typeParameter: KtTypeParameterSymbol, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.ConflictingUpperBounds(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } diff --git a/idea/testData/checker/MultipleBounds.fir.kt b/idea/testData/checker/MultipleBounds.fir.kt index 61869618ce5..60df6261d98 100644 --- a/idea/testData/checker/MultipleBounds.fir.kt +++ b/idea/testData/checker/MultipleBounds.fir.kt @@ -42,7 +42,7 @@ class Bar class Buzz where T : Bar, T : nioho class X -class Y where T : Foo, T : Bar +class Y<T> where T : Foo, T : Bar fun test2(t : T) where diff --git a/idea/testData/checker/TypeParameterBounds.fir.kt b/idea/testData/checker/TypeParameterBounds.fir.kt deleted file mode 100644 index 3fff15baa68..00000000000 --- a/idea/testData/checker/TypeParameterBounds.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -// See KT-9438: Enforce the Single Instantiation Inheritance Rule for type parameters - -interface A - -interface B - -interface D - -interface CorrectF where T : D, T : D - -fun bar() where T : D, T : D {} diff --git a/idea/testData/checker/TypeParameterBounds.kt b/idea/testData/checker/TypeParameterBounds.kt index 4d962cb6bef..b63efadfc4b 100644 --- a/idea/testData/checker/TypeParameterBounds.kt +++ b/idea/testData/checker/TypeParameterBounds.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // See KT-9438: Enforce the Single Instantiation Inheritance Rule for type parameters interface A