diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt index 5c5c24fb52e..848b59e325a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt @@ -3,7 +3,7 @@ open class A { } open class B : A { - override var test: Double = 20.0 + override var test: Double = 20.0 } class C() : A() { @@ -15,7 +15,7 @@ open class D() : B() { } class E(val value: T) : B() { - override var test: T = value + override var test: T = value } open class F(val value: T) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt index c059eb565ec..094a6426000 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt @@ -61,13 +61,13 @@ object FirOverrideChecker : FirRegularClassChecker() { private fun ConeKotlinType.substituteAllTypeParameters( overrideDeclaration: FirCallableMemberDeclaration<*>, - baseDeclarationSymbol: FirCallableSymbol<*>, + baseDeclaration: FirCallableDeclaration<*>, ): ConeKotlinType { if (overrideDeclaration.typeParameters.isEmpty()) { return this } - val parametersOwner = baseDeclarationSymbol.fir.safeAs() + val parametersOwner = baseDeclaration.safeAs() ?: return this val map = mutableMapOf() @@ -130,27 +130,35 @@ object FirOverrideChecker : FirRegularClassChecker() { } } + // See [OverrideResolver#isReturnTypeOkForOverride] private fun FirCallableMemberDeclaration<*>.checkReturnType( overriddenSymbols: List>, typeCheckerContext: AbstractTypeCheckerContext, context: CheckerContext, ): FirMemberDeclaration? { - val returnType = returnTypeRef.safeAs()?.type + val overridingReturnType = returnTypeRef.safeAs()?.type ?: return null // Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately. - if (returnType is ConeKotlinErrorType) { + if (overridingReturnType is ConeKotlinErrorType) { return null } val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it.fir).coneType.upperBoundIfFlexible() } for (it in bounds.indices) { - val restriction = bounds[it] - .substituteAllTypeParameters(this, overriddenSymbols[it]) + val overriddenDeclaration = overriddenSymbols[it].fir - if (!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, returnType, restriction)) { - return overriddenSymbols[it].fir.safeAs() + val overriddenReturnType = bounds[it].substituteAllTypeParameters(this, overriddenDeclaration) + + val isReturnTypeOkForOverride = + if (overriddenDeclaration is FirProperty && overriddenDeclaration.isVar) + AbstractTypeChecker.equalTypes(typeCheckerContext, overridingReturnType, overriddenReturnType) + else + AbstractTypeChecker.isSubtypeOf(typeCheckerContext, overridingReturnType, overriddenReturnType) + + if (!isReturnTypeOkForOverride) { + return overriddenDeclaration.safeAs() } } diff --git a/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt b/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt deleted file mode 100644 index 2d736b76b07..00000000000 --- a/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -interface Super { - var v: CharSequence - val v2: CharSequence -} - -class Sub: Super { - override var v: String = "fail" - override val v2: String = "ok" -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/subtyping/kt3159.kt b/compiler/testData/diagnostics/tests/subtyping/kt3159.kt index 11c335546d3..c4f6d9bca85 100644 --- a/compiler/testData/diagnostics/tests/subtyping/kt3159.kt +++ b/compiler/testData/diagnostics/tests/subtyping/kt3159.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface Super { var v: CharSequence val v2: CharSequence diff --git a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt index 57af86eaa66..3f25c0fadc5 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt @@ -18,7 +18,7 @@ class Case1 : Base() { override val a: Any? get() = TODO() - override var b: String + override var b: String get() = TODO() set(value) {} @@ -29,7 +29,7 @@ class Case1 : Base() { * TESTCASE NUMBER: 2 */ -class Case2(override val a: String, override var b: String) : Base() { +class Case2(override val a: String, override var b: String) : Base() { override fun foo(): CharSequence? { return "" }