From ac63d8b3bf167db7bfc903809b935d375b0641b6 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Sun, 27 Sep 2020 21:23:46 +0300 Subject: [PATCH] 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 --- .../kotlin/resolve/OverrideResolver.kt | 55 ++++++------------- .../multiplatform/overrideExpect/jvm/jvm.kt | 4 +- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt index 68e3d012988..2c0cafcd9a0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt @@ -795,19 +795,13 @@ class OverrideResolver( ) { if (overriddenDescriptors.size <= 1) return - val propertyDescriptor = descriptor as? PropertyDescriptor - for (overriddenDescriptor in overriddenDescriptors) { - if (propertyDescriptor != null) { - val overriddenPropertyDescriptor = - overriddenDescriptor.assertedCast { "$overriddenDescriptor is not a property" } - if (!isPropertyTypeOkForOverride(overriddenPropertyDescriptor, propertyDescriptor)) { - reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor) - } - } else { - if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) { - reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor) - } + require(descriptor !is PropertyDescriptor || overriddenDescriptor is PropertyDescriptor) { + "$overriddenDescriptor is not a property" + } + + if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) { + reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor) } } } @@ -852,15 +846,13 @@ class OverrideResolver( reportError.overridingFinalMember(memberDescriptor, overridden) } - if (propertyMemberDescriptor != null) { - val overriddenProperty = overridden.assertedCast { - "$overridden is overridden by property $propertyMemberDescriptor" + if (!isReturnTypeOkForOverride(overridden, memberDescriptor, kotlinTypeRefiner)) { + if (memberDescriptor is PropertyDescriptor) { + 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)) { @@ -872,7 +864,7 @@ class OverrideResolver( private fun isReturnTypeOkForOverride( superDescriptor: CallableDescriptor, subDescriptor: CallableDescriptor, - kotlinTypeRefiner: KotlinTypeRefiner + kotlinTypeRefiner: KotlinTypeRefiner, ): Boolean { val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false @@ -882,7 +874,11 @@ class OverrideResolver( 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( @@ -901,21 +897,6 @@ class OverrideResolver( 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 { val classDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(dataClass) as KtClassOrObject? if (classDeclaration?.modifierList != null) { diff --git a/idea/testData/multiplatform/overrideExpect/jvm/jvm.kt b/idea/testData/multiplatform/overrideExpect/jvm/jvm.kt index 114d6d436cc..7b7e579d9f5 100644 --- a/idea/testData/multiplatform/overrideExpect/jvm/jvm.kt +++ b/idea/testData/multiplatform/overrideExpect/jvm/jvm.kt @@ -7,7 +7,7 @@ interface Derived : Base { override fun Expect.expectInReceiver() - override val expectVal: Expect + override val expectVal: Expect - override var expectVar: Expect + override var expectVar: Expect }