提交 266432a4 编写于 作者: J Jinseong Jeon 提交者: Dmitriy Novozhilov

FIR checker: fix condition for property type mismatch on override

上级 065d0c66
...@@ -3,7 +3,7 @@ open class A { ...@@ -3,7 +3,7 @@ open class A {
} }
open class B : 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() { class C() : A() {
...@@ -15,7 +15,7 @@ open class D() : B() { ...@@ -15,7 +15,7 @@ open class D() : B() {
} }
class E<T : Double>(val value: T) : 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) { open class F<T : Number>(val value: T) {
......
...@@ -61,13 +61,13 @@ object FirOverrideChecker : FirRegularClassChecker() { ...@@ -61,13 +61,13 @@ object FirOverrideChecker : FirRegularClassChecker() {
private fun ConeKotlinType.substituteAllTypeParameters( private fun ConeKotlinType.substituteAllTypeParameters(
overrideDeclaration: FirCallableMemberDeclaration<*>, overrideDeclaration: FirCallableMemberDeclaration<*>,
baseDeclarationSymbol: FirCallableSymbol<*>, baseDeclaration: FirCallableDeclaration<*>,
): ConeKotlinType { ): ConeKotlinType {
if (overrideDeclaration.typeParameters.isEmpty()) { if (overrideDeclaration.typeParameters.isEmpty()) {
return this return this
} }
val parametersOwner = baseDeclarationSymbol.fir.safeAs<FirTypeParametersOwner>() val parametersOwner = baseDeclaration.safeAs<FirTypeParametersOwner>()
?: return this ?: return this
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>() val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
...@@ -130,27 +130,35 @@ object FirOverrideChecker : FirRegularClassChecker() { ...@@ -130,27 +130,35 @@ object FirOverrideChecker : FirRegularClassChecker() {
} }
} }
// See [OverrideResolver#isReturnTypeOkForOverride]
private fun FirCallableMemberDeclaration<*>.checkReturnType( private fun FirCallableMemberDeclaration<*>.checkReturnType(
overriddenSymbols: List<FirCallableSymbol<*>>, overriddenSymbols: List<FirCallableSymbol<*>>,
typeCheckerContext: AbstractTypeCheckerContext, typeCheckerContext: AbstractTypeCheckerContext,
context: CheckerContext, context: CheckerContext,
): FirMemberDeclaration? { ): FirMemberDeclaration? {
val returnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type val overridingReturnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
?: return null ?: return null
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately. // 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 return null
} }
val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it.fir).coneType.upperBoundIfFlexible() } val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it.fir).coneType.upperBoundIfFlexible() }
for (it in bounds.indices) { for (it in bounds.indices) {
val restriction = bounds[it] val overriddenDeclaration = overriddenSymbols[it].fir
.substituteAllTypeParameters(this, overriddenSymbols[it])
if (!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, returnType, restriction)) { val overriddenReturnType = bounds[it].substituteAllTypeParameters(this, overriddenDeclaration)
return overriddenSymbols[it].fir.safeAs()
val isReturnTypeOkForOverride =
if (overriddenDeclaration is FirProperty && overriddenDeclaration.isVar)
AbstractTypeChecker.equalTypes(typeCheckerContext, overridingReturnType, overriddenReturnType)
else
AbstractTypeChecker.isSubtypeOf(typeCheckerContext, overridingReturnType, overriddenReturnType)
if (!isReturnTypeOkForOverride) {
return overriddenDeclaration.safeAs()
} }
} }
......
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
// FIR_IDENTICAL
interface Super { interface Super {
var v: CharSequence var v: CharSequence
val v2: CharSequence val v2: CharSequence
......
...@@ -18,7 +18,7 @@ class Case1 : Base() { ...@@ -18,7 +18,7 @@ class Case1 : Base() {
override val a: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Any?<!> override val a: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Any?<!>
get() = TODO() get() = TODO()
override var b: String override var b: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>String<!>
get() = TODO() get() = TODO()
set(value) set(value)
{} {}
...@@ -29,7 +29,7 @@ class Case1 : Base() { ...@@ -29,7 +29,7 @@ class Case1 : Base() {
* TESTCASE NUMBER: 2 * 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?<!> { override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>CharSequence?<!> {
return "" return ""
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册