Unify code for checking return type on override for fun/property

This fixes issues with the refinement of property' return type because
for functions' return type we already perform refinement properly
This commit is contained in:
Dmitry Savvinov
2020-09-27 21:23:46 +03:00
parent 736ecf3e9f
commit ac63d8b3bf
2 changed files with 20 additions and 39 deletions
@@ -795,19 +795,13 @@ class OverrideResolver(
) { ) {
if (overriddenDescriptors.size <= 1) return if (overriddenDescriptors.size <= 1) return
val propertyDescriptor = descriptor as? PropertyDescriptor
for (overriddenDescriptor in overriddenDescriptors) { for (overriddenDescriptor in overriddenDescriptors) {
if (propertyDescriptor != null) { require(descriptor !is PropertyDescriptor || overriddenDescriptor is PropertyDescriptor) {
val overriddenPropertyDescriptor = "$overriddenDescriptor is not a property"
overriddenDescriptor.assertedCast<PropertyDescriptor> { "$overriddenDescriptor is not a property" } }
if (!isPropertyTypeOkForOverride(overriddenPropertyDescriptor, propertyDescriptor)) {
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor) if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) {
} reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
} else {
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) {
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
}
} }
} }
} }
@@ -852,15 +846,13 @@ class OverrideResolver(
reportError.overridingFinalMember(memberDescriptor, overridden) reportError.overridingFinalMember(memberDescriptor, overridden)
} }
if (propertyMemberDescriptor != null) { if (!isReturnTypeOkForOverride(overridden, memberDescriptor, kotlinTypeRefiner)) {
val overriddenProperty = overridden.assertedCast<PropertyDescriptor> { if (memberDescriptor is PropertyDescriptor) {
"$overridden is overridden by property $propertyMemberDescriptor" require(overridden is PropertyDescriptor) { "$overridden is overridden by property $propertyMemberDescriptor" }
reportError.propertyTypeMismatchOnOverride(memberDescriptor, overridden)
} else {
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
} }
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor, kotlinTypeRefiner)) {
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
}
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor, kotlinTypeRefiner)) {
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
} }
if (checkPropertyKind(overridden, true) && checkPropertyKind(memberDescriptor, false)) { if (checkPropertyKind(overridden, true) && checkPropertyKind(memberDescriptor, false)) {
@@ -872,7 +864,7 @@ class OverrideResolver(
private fun isReturnTypeOkForOverride( private fun isReturnTypeOkForOverride(
superDescriptor: CallableDescriptor, superDescriptor: CallableDescriptor,
subDescriptor: CallableDescriptor, subDescriptor: CallableDescriptor,
kotlinTypeRefiner: KotlinTypeRefiner kotlinTypeRefiner: KotlinTypeRefiner,
): Boolean { ): Boolean {
val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false
@@ -882,7 +874,11 @@ class OverrideResolver(
val substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE)!! val substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE)!!
return NewKotlinTypeCheckerImpl(kotlinTypeRefiner).isSubtypeOf(subReturnType, substitutedSuperReturnType) val typeChecker = NewKotlinTypeCheckerImpl(kotlinTypeRefiner)
return if (superDescriptor is PropertyDescriptor && superDescriptor.isVar)
typeChecker.equalTypes(subReturnType, substitutedSuperReturnType)
else
typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType)
} }
private fun prepareTypeSubstitutor( private fun prepareTypeSubstitutor(
@@ -901,21 +897,6 @@ class OverrideResolver(
return IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor() return IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor()
} }
private fun isPropertyTypeOkForOverride(
superDescriptor: PropertyDescriptor,
subDescriptor: PropertyDescriptor
): Boolean {
val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false
val substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.type, Variance.OUT_VARIANCE)!!
return if (superDescriptor.isVar) {
KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.type, substitutedSuperReturnType)
} else {
KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.type, substitutedSuperReturnType)
}
}
private fun findDataModifierForDataClass(dataClass: DeclarationDescriptor): PsiElement { private fun findDataModifierForDataClass(dataClass: DeclarationDescriptor): PsiElement {
val classDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(dataClass) as KtClassOrObject? val classDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(dataClass) as KtClassOrObject?
if (classDeclaration?.modifierList != null) { if (classDeclaration?.modifierList != null) {
+2 -2
View File
@@ -7,7 +7,7 @@ interface Derived : Base {
override fun Expect.expectInReceiver() override fun Expect.expectInReceiver()
override val expectVal: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Expect<!> override val expectVal: Expect
override var expectVar: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Expect<!> override var expectVar: Expect
} }