FIR checker: fix condition for property type mismatch on override
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
065d0c66ab
commit
266432a482
+2
-2
@@ -3,7 +3,7 @@ open class A {
|
||||
}
|
||||
|
||||
open class B : A {
|
||||
override var test: Double = 20.0
|
||||
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Double<!> = 20.0
|
||||
}
|
||||
|
||||
class C() : A() {
|
||||
@@ -15,7 +15,7 @@ open class D() : B() {
|
||||
}
|
||||
|
||||
class E<T : Double>(val value: T) : B() {
|
||||
override var test: T = value
|
||||
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>T<!> = value
|
||||
}
|
||||
|
||||
open class F<T : Number>(val value: T) {
|
||||
|
||||
+16
-8
@@ -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<FirTypeParametersOwner>()
|
||||
val parametersOwner = baseDeclaration.safeAs<FirTypeParametersOwner>()
|
||||
?: return this
|
||||
|
||||
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
|
||||
@@ -130,27 +130,35 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
// See [OverrideResolver#isReturnTypeOkForOverride]
|
||||
private fun FirCallableMemberDeclaration<*>.checkReturnType(
|
||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||
typeCheckerContext: AbstractTypeCheckerContext,
|
||||
context: CheckerContext,
|
||||
): FirMemberDeclaration? {
|
||||
val returnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
|
||||
val overridingReturnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
interface Super {
|
||||
var v: CharSequence
|
||||
val v2: CharSequence
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ class Case1 : Base() {
|
||||
|
||||
override val a: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Any?<!>
|
||||
get() = TODO()
|
||||
override var b: String
|
||||
override var b: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>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: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>String<!>) : Base() {
|
||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>CharSequence?<!> {
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user