FIR checker: fix condition for property type mismatch on override

This commit is contained in:
Jinseong Jeon
2021-02-03 22:11:18 -08:00
committed by Dmitriy Novozhilov
parent 065d0c66ab
commit 266432a482
5 changed files with 21 additions and 21 deletions
@@ -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) {
@@ -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
@@ -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 ""
}