diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/conflictingOverloads.kt index 9b4875e8c12..e67fcfbbe9d 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 kek(t: T) {} +fun kek(t: T) where T : (String) -> Any?, T : Char {} +fun 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 mem(t: T) where T : () -> Boolean, T : String {} +fun mem(t: T) where T : String, T : () -> Boolean {} class M { companion object {} diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt index 4a98050c4e7..778680b90bd 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt @@ -14,7 +14,7 @@ open class D() : B() { override var test: Char = '\n' } -class E(val value: T) : B() { +class EDouble>(val value: T) : B() { override var test: T = value } @@ -22,14 +22,14 @@ open class F(val value: T) { open var rest: T = value } -class G(val balue: E) : F(balue) { +class GDouble>(val balue: E) : F(balue) { override var rest: E = balue } -class H(val balue: E) : F(balue) { +class HString>(val balue: E) : F(balue) { override var rest: E = balue // no report because of INAPPLICABLE_CANDIDATE } -class M(val balue: E) : F(3.14) { +class MString>(val balue: E) : F(3.14) { override var rest: E = balue } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt index c967908f762..a6f64235b3b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt @@ -15,7 +15,7 @@ open class D() : B() { override fun test(): Char = '\n' } -class E(val value: T) : B() { +class EDouble>(val value: T) : B() { override fun test(): T = value } @@ -23,15 +23,15 @@ open class F(val value: T) { open fun rest(): T = value } -class G(val balue: E) : F(balue) { +class GDouble>(val balue: E) : F(balue) { override fun rest(): E = balue } -class H(val balue: E) : F(balue) { +class HString>(val balue: E) : F(balue) { override fun rest(): E = balue // no report because of INAPPLICABLE_CANDIDATE } -class M(val balue: E) : F(3.14) { +class MString>(val balue: E) : F(3.14) { override fun rest(): E = balue } diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index c13c8492bea..4e5046a807b 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -35,6 +35,7 @@ fun main(args: Array) { alias("RegularClassChecker") alias("ConstructorChecker") alias("FileChecker") + alias("FirTypeParameterChecker") additional( fieldName = "controlFlowAnalyserCheckers", 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 09baaf16e1b..88b53f681a5 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 @@ -289,6 +289,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val TYPE_PARAMETER_AS_REIFIED by error { parameter("typeParameter") } + + val FINAL_UPPER_BOUND by warning { + parameter("type") + } } val REFLECTION by object : DiagnosticGroup("Reflection") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ComposedDeclarationCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ComposedDeclarationCheckers.kt index d4900c077c5..550110edc5f 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ComposedDeclarationCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ComposedDeclarationCheckers.kt @@ -33,6 +33,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { get() = _constructorCheckers override val fileCheckers: Set get() = _fileCheckers + override val typeParameterCheckers: Set + get() = _typeParameterCheckers override val controlFlowAnalyserCheckers: Set get() = _controlFlowAnalyserCheckers override val variableAssignmentCfaBasedCheckers: Set @@ -47,6 +49,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { private val _regularClassCheckers: MutableSet = mutableSetOf() private val _constructorCheckers: MutableSet = mutableSetOf() private val _fileCheckers: MutableSet = mutableSetOf() + private val _typeParameterCheckers: MutableSet = mutableSetOf() private val _controlFlowAnalyserCheckers: MutableSet = mutableSetOf() private val _variableAssignmentCfaBasedCheckers: MutableSet = mutableSetOf() @@ -61,6 +64,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { _regularClassCheckers += checkers.regularClassCheckers _constructorCheckers += checkers.constructorCheckers _fileCheckers += checkers.fileCheckers + _typeParameterCheckers += checkers.typeParameterCheckers _controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers _variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt index 99ee2ef55de..6f57817fb5a 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt @@ -28,6 +28,7 @@ abstract class DeclarationCheckers { open val regularClassCheckers: Set = emptySet() open val constructorCheckers: Set = emptySet() open val fileCheckers: Set = emptySet() + open val typeParameterCheckers: Set = emptySet() open val controlFlowAnalyserCheckers: Set = emptySet() open val variableAssignmentCfaBasedCheckers: Set = emptySet() @@ -41,4 +42,5 @@ abstract class DeclarationCheckers { @CheckersComponentInternal internal val allRegularClassCheckers: Set get() = regularClassCheckers + memberDeclarationCheckers + basicDeclarationCheckers + classCheckers @CheckersComponentInternal internal val allConstructorCheckers: Set get() = constructorCheckers + functionCheckers + basicDeclarationCheckers + memberDeclarationCheckers @CheckersComponentInternal internal val allFileCheckers: Set get() = fileCheckers + basicDeclarationCheckers + @CheckersComponentInternal internal val allTypeParameterCheckers: Set get() = typeParameterCheckers + basicDeclarationCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerAliases.kt index ef044c9c79b..c79a2bcf2f9 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerAliases.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter typealias FirBasicDeclarationChecker = FirDeclarationChecker typealias FirMemberDeclarationChecker = FirDeclarationChecker @@ -29,3 +30,4 @@ typealias FirClassChecker = FirDeclarationChecker> typealias FirRegularClassChecker = FirDeclarationChecker typealias FirConstructorChecker = FirDeclarationChecker typealias FirFileChecker = FirDeclarationChecker +typealias FirTypeParameterChecker = FirDeclarationChecker 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 3acc5bdfbc4..21156a72555 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 @@ -214,6 +214,7 @@ 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() // 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/cfa/FirReturnsImpliesAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt index 361c0798246..1a7199cd7d2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirReturnsImpliesAnalyzer.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription @@ -199,9 +200,6 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() { else -> true } - fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) = - type != null && AbstractTypeChecker.isSubtypeOf(context, type, this) - private fun simpleTypeStatement(realVar: RealVariable, exactType: Boolean, type: ConeKotlinType): MutableTypeStatement { return MutableTypeStatement( realVar, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 12de637c3ce..215b763fb06 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -5,13 +5,11 @@ package org.jetbrains.kotlin.fir.analysis.checkers -import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier @@ -30,16 +28,16 @@ import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtModifierList -import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal fun FirClass<*>.unsubstitutedScope(context: CheckerContext) = @@ -321,3 +319,81 @@ val FirValueParameter.hasValOrVar: Boolean val source = this.source ?: return false return source.getChild(VAL_VAR_TOKEN_SET) != null } + +fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) = + type != null && AbstractTypeChecker.isSubtypeOf(context, type, this) + +fun KotlinTypeMarker.isSubtypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) = + type != null && AbstractTypeChecker.isSubtypeOf(context, this, type) + +fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { + if (this.isMarkedNullable) { + return true + } + val clazz = toRegularClass(session) ?: return true + if (clazz.isEnumClass || clazz.isExpect || clazz.modality != Modality.FINAL) { + return true + } + + clazz.typeParameters.forEachIndexed { idx, typeParameterRef -> + val typeParameter = typeParameterRef.symbol.fir + val typeProjection = typeArguments[idx] + + if (typeProjection.isStarProjection) { + return true + } + + val argument = typeProjection.type!! //safe because it is not a star + + when (typeParameter.variance) { + Variance.INVARIANT -> + when (typeProjection.kind) { + ProjectionKind.INVARIANT -> + if (lowerThanBound(session.typeContext, argument, typeParameter) || argument.canHaveSubtypes(session)) { + return true + } + ProjectionKind.IN -> + if (lowerThanBound(session.typeContext, argument, typeParameter)) { + return true + } + ProjectionKind.OUT -> + if (argument.canHaveSubtypes(session)) { + return true + } + ProjectionKind.STAR -> + return true + } + Variance.IN_VARIANCE -> + if (typeProjection.kind != ProjectionKind.OUT) { + if (lowerThanBound(session.typeContext, argument, typeParameter)) { + return true + } + } else { + if (argument.canHaveSubtypes(session)) { + return true + } + } + Variance.OUT_VARIANCE -> + if (typeProjection.kind != ProjectionKind.IN) { + if (argument.canHaveSubtypes(session)) { + return true + } + } else { + if (lowerThanBound(session.typeContext, argument, typeParameter)) { + return true + } + } + } + } + + return false +} + +private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinType, typeParameter: FirTypeParameter): Boolean { + typeParameter.bounds.forEach { boundTypeRef -> + if (argument != boundTypeRef.coneType && argument.isSubtypeOf(context, boundTypeRef.coneType)) { + return true + } + } + return false +} 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 new file mode 100644 index 00000000000..a01c981b086 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTypeParameterBoundsChecker.kt @@ -0,0 +1,30 @@ +/* + * 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.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.canHaveSubtypes +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.declarations.* +import org.jetbrains.kotlin.fir.types.coneType + +object FirTypeParameterBoundsChecker : FirTypeParameterChecker() { + + override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) { + val containingDeclaration = context.containingDeclarations.lastOrNull() + if (containingDeclaration is FirConstructor) return + if (containingDeclaration is FirSimpleFunction && containingDeclaration.isOverride) return + if (containingDeclaration is FirProperty && containingDeclaration.isOverride) return + + declaration.symbol.fir.bounds.forEach { bound -> + if (!bound.coneType.canHaveSubtypes(context.session)) { + reporter.reportOn(bound.source, FirErrors.FINAL_UPPER_BOUND, bound.coneType, context) + } + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt index 075a470ee75..e39b01910de 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt @@ -61,7 +61,7 @@ class DeclarationCheckersDiagnosticComponent( } override fun visitTypeParameter(typeParameter: FirTypeParameter, data: CheckerContext) { - checkers.allBasicDeclarationCheckers.check(typeParameter, data, reporter) + checkers.allTypeParameterCheckers.check(typeParameter, data, reporter) } override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) { 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 8cfc3f1dc67..1f0c4e2125c 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 @@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPRESSION_OF_NUL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE_SUBCLASS @@ -438,6 +439,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { ) map.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead", SYMBOL) + map.put( + FINAL_UPPER_BOUND, + "''{0}'' is a final type, and thus a value of the type parameter is predetermined", + RENDER_TYPE + ) // Reflection map.put( diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt index 301d71e72cb..425fb763b78 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt @@ -87,4 +87,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() { override val variableAssignmentCfaBasedCheckers: Set = setOf( FirPropertyInitializationAnalyzer, ) + + override val typeParameterCheckers: Set = setOf( + FirTypeParameterBoundsChecker, + ) } diff --git a/compiler/testData/diagnostics/tests/Bounds.fir.kt b/compiler/testData/diagnostics/tests/Bounds.fir.kt index 15fc37429b1..2c1c71a57fe 100644 --- a/compiler/testData/diagnostics/tests/Bounds.fir.kt +++ b/compiler/testData/diagnostics/tests/Bounds.fir.kt @@ -40,4 +40,4 @@ fun test() { fun foo() {} fun bar() {} -fun Int.buzz() : Unit {} +fun Int> Int.buzz() : Unit {} diff --git a/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt b/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt index 82718934296..7b89a9b9f69 100644 --- a/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt +++ b/compiler/testData/diagnostics/tests/MultipleBounds.fir.kt @@ -43,12 +43,12 @@ fun test() { class Foo() {} -class Bar +class BarFoo> -class Buzz where T : Bar, T : nioho +class Buzz where T : Bar, T : nioho -class X -class Y where T : Foo, T : Bar +class XFoo> +class Y where T : Foo, T : Bar fun test2(t : T) where diff --git a/compiler/testData/diagnostics/tests/callableReference/generic/explicitTypeArguments.fir.kt b/compiler/testData/diagnostics/tests/callableReference/generic/explicitTypeArguments.fir.kt index d9af7bc2c50..df2b4df88d9 100644 --- a/compiler/testData/diagnostics/tests/callableReference/generic/explicitTypeArguments.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/generic/explicitTypeArguments.fir.kt @@ -5,7 +5,7 @@ fun takeFun(f: (T) -> Unit) {} fun callFun(f: (T) -> R): R = TODO() fun foo(s: T) {} -fun fooInt(s: T) {} +fun Int> fooInt(s: T) {} open class Wrapper(val value: T) fun > createWrapper(s: T): R = TODO() diff --git a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.fir.kt b/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.fir.kt deleted file mode 100644 index 425e4ecb019..00000000000 --- a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.fir.kt +++ /dev/null @@ -1,97 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -// SKIP_TXT -// Issues: KT-25105 - -class Message1 -class Task -object Message2 -enum class Message3 -data class Message4(val x: Int) - -sealed class Message5 { - open fun execute() {} -} - -interface Manager { - fun execute1(task: Task) {} - fun execute2(task: T) {} - fun execute3() {} - fun execute4() {} - fun execute5() {} - val A.x get() = 10 - var A.y - get() = 10 - set(value) {} -} - -object MessageManager1 : Manager { - override fun execute1(task: Task) {} - override fun execute2(task: T) {} - override fun execute3() {} -} - -object MessageManager2 : Manager { - override fun execute4() {} -} - -object MessageManager3 : Manager { - override fun execute5() {} -} - -class MessageManager4 : Manager { - override fun execute1(task: Task) {} - override fun execute2(task: T) {} - override fun execute3() {} -} - -class MessageManager5 : Manager { - override fun execute4() {} -} - -class MessageManager6 : Manager { - override fun execute5() {} -} - -interface MessageManager7 : Manager { - override fun execute5() {} -} - -interface MessageManager8 : Manager { - override fun execute1(task: Task) {} - override fun execute2(task: T) {} - override fun execute3() {} -} - -interface MessageManager9 : Manager { - override fun execute4() {} -} - -object MessageManager10 : Message5() { - override fun execute() {} -} - -class MessageManager11 : Message5>() { - override fun > execute() {} -} - -data class MessageManager12(val x: Int) : Message5() { - override fun execute() {} -} - -sealed class MessageManager13 : Message5() { - override fun execute() {} -} - -class MessageManager14 : Manager { - override val T.x get() = 10 - override var T.y - get() = 10 - set(value) {} -} - -object MessageManager15 : Manager { - override val T.x get() = 10 - override var T.y - get() = 10 - set(value) {} -} diff --git a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.kt b/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.kt index 26449d3c54c..ad8472e6f2c 100644 --- a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.kt +++ b/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithOverride.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER // SKIP_TXT // Issues: KT-25105 diff --git a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithoutOverride.fir.kt b/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithoutOverride.fir.kt index d6c18a73b49..56570792dbd 100644 --- a/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithoutOverride.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/finalUpperBoundWithoutOverride.fir.kt @@ -10,9 +10,9 @@ data class Message4(val x: Int) interface Manager {} object MessageManager1 : Manager { - fun execute1(task: Task) {} - fun execute2(task: T) {} - fun execute3() {} + fun Message1> execute1(task: Task) {} + fun Int> execute2(task: T) {} + fun Message2> execute3() {} } object MessageManager2 : Manager { @@ -20,13 +20,13 @@ object MessageManager2 : Manager { } object MessageManager3 : Manager { - fun execute5() {} + fun Message4> execute5() {} } class MessageManager4 : Manager { - fun execute1(task: Task) {} - fun execute2(task: T) {} - fun execute3() {} + fun Message1> execute1(task: Task) {} + fun Int> execute2(task: T) {} + fun Message2> execute3() {} } class MessageManager5 : Manager { @@ -34,17 +34,17 @@ class MessageManager5 : Manager { } class MessageManager6 : Manager { - fun execute5() {} + fun Message4> execute5() {} } interface MessageManager7 : Manager { - fun execute5() {} + fun Message4> execute5() {} } interface MessageManager8 : Manager { - fun execute1(task: Task) {} - fun execute2(task: T) {} - fun execute3() {} + fun Message1> execute1(task: Task) {} + fun Int> execute2(task: T) {} + fun Message2> execute3() {} } interface MessageManager9 : Manager { @@ -52,7 +52,7 @@ interface MessageManager9 : Manager { } object MessageManager10 : Message5() { - fun execute() {} + fun Int> execute() {} } class MessageManager11 : Message5<Message5>() { @@ -60,7 +60,7 @@ class MessageManager11 : Message5<Message5() { - fun execute() {} + fun Message2> execute() {} } sealed class MessageManager13 : Message5() { @@ -68,15 +68,15 @@ sealed class MessageManager13 : Message5() { } class MessageManager14 : Manager { - val T.x get() = 10 - var T.y + val Message2> T.x get() = 10 + var Message2> T.y get() = 10 set(value) {} } object MessageManager15 : Manager { - val T.x get() = 10 - var T.y + val Int> T.x get() = 10 + var Int> T.y get() = 10 set(value) {} } diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.fir.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.fir.kt index 6190d21fa8e..497fe81964b 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.fir.kt @@ -53,7 +53,7 @@ fun testCaptured(cSub: SubInv, cInv: Inv) { fun testVariableWithBound() { fun createWithNumberBound(): Inv = TODO() - fun createWithIntBound(): Inv = TODO() + fun Int> createWithIntBound(): Inv = TODO() val c1 = select(SubInv(), createWithNumberBound()) diff --git a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt index 106db4f7c00..e8bb451ab9f 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.fir.kt @@ -15,4 +15,4 @@ enum class E1 class A5 where T : C1, T : E1 object O1 -class A6 where T : O1, T : C2 +class A6 where T : O1, T : C2 diff --git a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt index 1edf45e1e0f..4b2f3531770 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.fir.kt @@ -2,7 +2,7 @@ fun > f1() {} fun > f2() {} fun f3() where A : Array, A : Array {} -fun f4() {} +fun IntArray> f4() {} fun f5() where T : Array {} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt index 44b83b4e1e1..99c0fdb7cca 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt @@ -110,15 +110,15 @@ fun T.case_19_4(): Boolean? { } // TESTCASE NUMBER: 20 -fun T?.case_20_1(): Boolean { +fun String> T?.case_20_1(): Boolean { contract { returns(true) implies (this@case_20_1 != null) } return this@case_20_1 != null } -fun T?.case_20_2(): Boolean { +fun String> T?.case_20_2(): Boolean { contract { returns(true) implies (this@case_20_2 == null) } return this@case_20_2 == null } -fun T?.case_20_3(): Boolean { +fun String> T?.case_20_3(): Boolean { contract { returns(false) implies (this@case_20_3 != null) } return !(this@case_20_3 != null) } @@ -132,11 +132,11 @@ fun T.case_21_2(): Boolean { contract { returns(true) implies (this@case_21_2 == null) } return this@case_21_2 == null } -fun T?.case_21_5(): Boolean? { +fun String> T?.case_21_5(): Boolean? { contract { returnsNotNull() implies (this@case_21_5 != null) } return if (this@case_21_5 != null) true else null } -fun T?.case_21_7(): Boolean? { +fun String> T?.case_21_7(): Boolean? { contract { returns(null) implies (this@case_21_7 != null) } return if (this@case_21_7 != null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt index 09a961797bf..5d0f640a453 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt @@ -20,11 +20,11 @@ fun T.case_2() { } // TESTCASE NUMBER: 3 -fun T?.case_3_1() { +fun String> T?.case_3_1() { contract { returns() implies (this@case_3_1 == null) } if (!(this@case_3_1 == null)) throw Exception() } -fun T?.case_3_2() { +fun String> T?.case_3_2() { contract { returns() implies (this@case_3_2 != null) } if (!(this@case_3_2 != null)) throw Exception() } @@ -76,19 +76,19 @@ fun T.case_6_4(): Boolean? { } // TESTCASE NUMBER: 7 -fun T?.case_7_1(): Boolean { +fun String> T?.case_7_1(): Boolean { contract { returns(true) implies (this@case_7_1 == null) } return this@case_7_1 == null } -fun T?.case_7_2(): Boolean { +fun String> T?.case_7_2(): Boolean { contract { returns(false) implies (this@case_7_2 != null) } return !(this@case_7_2 != null) } -fun T?.case_7_3(): Boolean? { +fun String> T?.case_7_3(): Boolean? { contract { returnsNotNull() implies (this@case_7_3 != null) } return if (this@case_7_3 != null) true else null } -fun T?.case_7_4(): Boolean? { +fun String> T?.case_7_4(): Boolean? { contract { returns(null) implies (this@case_7_4 != null) } return if (this@case_7_4 != null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt index 762a2b8bc51..a432ca8122a 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt @@ -20,11 +20,11 @@ fun T.case_2() { } // TESTCASE NUMBER: 3 -fun T?.case_3_1() { +fun String> T?.case_3_1() { contract { returns() implies (this@case_3_1 != null) } if (!(this@case_3_1 != null)) throw Exception() } -fun T?.case_3_2() { +fun String> T?.case_3_2() { contract { returns() implies (this@case_3_2 == null) } if (!(this@case_3_2 == null)) throw Exception() } @@ -76,47 +76,47 @@ fun T.case_6_4(): Boolean? { } // TESTCASE NUMBER: 7 -fun T?.case_7_1(): Boolean { +fun String> T?.case_7_1(): Boolean { contract { returns(true) implies (this@case_7_1 != null) } return this@case_7_1 != null } -fun T?.case_7_2(): Boolean { +fun String> T?.case_7_2(): Boolean { contract { returns(true) implies (this@case_7_2 == null) } return this@case_7_2 == null } -fun T?.case_7_3(): Boolean? { +fun String> T?.case_7_3(): Boolean? { contract { returnsNotNull() implies (this@case_7_3 == null) } return if (this@case_7_3 == null) true else null } -fun T?.case_7_4(): Boolean? { +fun String> T?.case_7_4(): Boolean? { contract { returns(null) implies (this@case_7_4 == null) } return if (this@case_7_4 == null) null else true } -fun T?.case_7_5(): Boolean { +fun String> T?.case_7_5(): Boolean { contract { returns(false) implies (this@case_7_5 == null) } return !(this@case_7_5 == null) } -fun T?.case_7_6(): Boolean? { +fun String> T?.case_7_6(): Boolean? { contract { returnsNotNull() implies (this@case_7_6 != null) } return if (this@case_7_6 != null) true else null } -fun T?.case_7_7(): Boolean? { +fun String> T?.case_7_7(): Boolean? { contract { returns(null) implies (this@case_7_7 != null) } return if (this@case_7_7 != null) null else true } -fun T?.case_7_8(): Boolean { +fun String> T?.case_7_8(): Boolean { contract { returns(false) implies (this@case_7_8 != null) } return !(this@case_7_8 != null) } -fun T?.case_7_9(): Boolean { +fun String> T?.case_7_9(): Boolean { contract { returns(false) implies (this@case_7_9 == null) } return !(this@case_7_9 == null) } -fun T?.case_7_10(): Boolean? { +fun String> T?.case_7_10(): Boolean? { contract { returnsNotNull() implies (this@case_7_10 == null) } return if (this@case_7_10 == null) true else null } -fun T?.case_7_11(): Boolean? { +fun String> T?.case_7_11(): Boolean? { contract { returns(null) implies (this@case_7_11 == null) } return if (this@case_7_11 == null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt index c4dd4c9db1e..43be60b7abe 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt @@ -3,7 +3,7 @@ import kotlin.contracts.* // TESTCASE NUMBER: 1 -fun T.case_1(): Boolean? { +fun Boolean>T.case_1(): Boolean? { contract { returns(null) implies (!this@case_1) } return if (!this) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt index c76aef1cda7..946e4fef528 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt @@ -9,7 +9,7 @@ fun Boolean?.case_1(): Boolean { } // TESTCASE NUMBER: 2 -fun T?.case_2(): Boolean { +fun Boolean>T?.case_2(): Boolean { contract { returns(true) implies (this@case_2 != null && this@case_2 !is Nothing && this@case_2) } return this != null && this !is Nothing && this } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt index c81cd05ccb0..44a67da46d3 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt @@ -10,7 +10,7 @@ fun T.case_1() { } // TESTCASE NUMBER: 2 -fun T?.case_2(value_1: K?) { +fun String> T?.case_2(value_1: K?) { contract { returns() implies (this@case_2 is T && value_1 is K) } if (!(this@case_2 is T && value_1 is K)) throw Exception() } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt index 779e59e9221..e4e4de283a2 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt @@ -36,7 +36,7 @@ class case_4 : ClassLevel3() { return this == null } - fun T.case_4_2() { + fun Boolean>T.case_4_2() { contract { returns() implies (!this@case_4_2) } if (this) throw Exception() } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/4.fir.kt index 5857d42bc0e..846cf0d2216 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/4.fir.kt @@ -35,7 +35,7 @@ inline fun case_3(x: Any?) { } // TESTCASE NUMBER: 4 -inline fun case_4(x: Any?) { +inline fun Boolean>case_4(x: Any?) { if (x is Int is T == null) { x x.inv() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.fir.kt index 08af6541739..763e156a4b6 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.fir.kt @@ -97,8 +97,8 @@ fun case_9() { * UNEXPECTED BEHAVIOUR * ISSUES: KT-22175 */ -fun T?.case_10() = this -fun T?.case_10() = this +fun String> T?.case_10() = this +fun Int> T?.case_10() = this fun case_10() { var x: Int? = 10 x = null @@ -106,7 +106,7 @@ fun case_10() { } // TESTCASE NUMBER: 11 -fun T?.case_11() = this +fun String> T?.case_11() = this fun case_11() { var x: Int? = 10 x = null 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 489bf6bcdf4..6d722502ef6 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 @@ -881,6 +881,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.FINAL_UPPER_BOUND) { firDiagnostic -> + FinalUpperBoundImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), + 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 222c5d08cbf..329e393adfe 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 @@ -628,6 +628,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val typeParameter: KtTypeParameterSymbol } + abstract class FinalUpperBound : KtFirDiagnostic() { + override val diagnosticClass get() = FinalUpperBound::class + abstract val type: KtType + } + 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 4a92fc20e69..06418d55778 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 @@ -1010,6 +1010,14 @@ internal class TypeParameterAsReifiedImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class FinalUpperBoundImpl( + override val type: KtType, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.FinalUpperBound(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ExtensionInClassReferenceNotAllowedImpl( override val referencedDeclaration: KtCallableSymbol, firDiagnostic: FirPsiDiagnostic<*>,