Refine types of type parameters before checking their equality in OverridingUtil

This commit is contained in:
Dmitry Savvinov
2020-09-25 13:25:51 +03:00
parent 80f4061a3d
commit ac107f362e
3 changed files with 40 additions and 21 deletions
@@ -38,9 +38,12 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractFakeOverride
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.checker.NewKotlinTypeCheckerImpl
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import java.util.*
@@ -74,7 +77,7 @@ class OverrideResolver(
val inheritedMemberErrors = CollectErrorInformationForInheritedMembersStrategy(klass, classDescriptor)
checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors)
checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors, kotlinTypeRefiner)
inheritedMemberErrors.doReportErrors()
}
@@ -378,7 +381,7 @@ class OverrideResolver(
override fun varOverriddenByVal(overriding: CallableMemberDescriptor, overridden: CallableMemberDescriptor) {
throw IllegalStateException("Component functions are not properties")
}
})
}, kotlinTypeRefiner)
}
private fun checkOverrideForCopyFunction(copyFunction: CallableMemberDescriptor) {
@@ -561,18 +564,25 @@ class OverrideResolver(
fun getMissingImplementations(classDescriptor: ClassDescriptor): Set<CallableMemberDescriptor> {
val collector = CollectMissingImplementationsStrategy()
checkInheritedAndDelegatedSignatures(classDescriptor, collector, null)
// Note that it is fine to pass default refiner here. Reason:
// 1. We bind overrides with proper refiners and [checkInheritedAndDelegatedSignatures] skips all properly-bound overrides,
// so we would consider only unbound overrides
// 2. Using default refiner instead of proper one can only increase amount of type mismatches, not decrease it
// Putting 1 and 2 together means that using default refiner might make already unbound overrides even "more unbound", which
// isn't an issue for case of [getMissingImplementations]
checkInheritedAndDelegatedSignatures(classDescriptor, collector, null, KotlinTypeRefiner.Default)
return collector.shouldImplement
}
private fun checkInheritedAndDelegatedSignatures(
classDescriptor: ClassDescriptor,
inheritedReportStrategy: CheckInheritedSignaturesReportStrategy,
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?,
kotlinTypeRefiner: KotlinTypeRefiner
) {
for (member in DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)) {
if (member is CallableMemberDescriptor) {
checkInheritedAndDelegatedSignatures(member, inheritedReportStrategy, overrideReportStrategyForDelegates)
checkInheritedAndDelegatedSignatures(member, inheritedReportStrategy, overrideReportStrategyForDelegates, kotlinTypeRefiner)
}
}
}
@@ -580,7 +590,8 @@ class OverrideResolver(
private fun checkInheritedAndDelegatedSignatures(
descriptor: CallableMemberDescriptor,
reportingStrategy: CheckInheritedSignaturesReportStrategy,
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?,
kotlinTypeRefiner: KotlinTypeRefiner
) {
val kind = descriptor.kind
if (kind != FAKE_OVERRIDE && kind != DELEGATION) return
@@ -606,10 +617,10 @@ class OverrideResolver(
return
}
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy)
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy, kotlinTypeRefiner)
if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates)
checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates, kotlinTypeRefiner)
}
if (kind != DELEGATION) {
@@ -632,7 +643,7 @@ class OverrideResolver(
1 ->
if (kind != DELEGATION) {
val implementation = concreteOverridden.first()
collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementation).forEach {
collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementation, kotlinTypeRefiner).forEach {
reportingStrategy.abstractMemberWithMoreSpecificType(it, implementation)
}
}
@@ -703,9 +714,10 @@ class OverrideResolver(
private fun collectAbstractMethodsWithMoreSpecificReturnType(
abstractOverridden: List<CallableMemberDescriptor>,
implementation: CallableMemberDescriptor
implementation: CallableMemberDescriptor,
kotlinTypeRefiner: KotlinTypeRefiner
): List<CallableMemberDescriptor> =
abstractOverridden.filter { abstractMember -> !isReturnTypeOkForOverride(abstractMember, implementation) }
abstractOverridden.filter { abstractMember -> !isReturnTypeOkForOverride(abstractMember, implementation, kotlinTypeRefiner) }
private fun getRelevantDirectlyOverridden(
overriddenByParent: MutableMap<CallableMemberDescriptor, Set<CallableMemberDescriptor>>,
@@ -778,7 +790,8 @@ class OverrideResolver(
private fun checkInheritedDescriptorsGroup(
descriptor: CallableMemberDescriptor,
overriddenDescriptors: Collection<CallableMemberDescriptor>,
reportingStrategy: CheckInheritedSignaturesReportStrategy
reportingStrategy: CheckInheritedSignaturesReportStrategy,
kotlinTypeRefiner: KotlinTypeRefiner
) {
if (overriddenDescriptors.size <= 1) return
@@ -792,7 +805,7 @@ class OverrideResolver(
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor)
}
} else {
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor)) {
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) {
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
}
}
@@ -806,7 +819,7 @@ class OverrideResolver(
) {
val overriddenDescriptors = declared.overriddenDescriptors
checkOverridesForMember(declared, overriddenDescriptors, reportError)
checkOverridesForMember(declared, overriddenDescriptors, reportError, kotlinTypeRefiner)
if (overriddenDescriptors.isEmpty()) {
val containingDeclaration = declared.containingDeclaration
@@ -829,7 +842,8 @@ class OverrideResolver(
private fun checkOverridesForMember(
memberDescriptor: CallableMemberDescriptor,
overriddenDescriptors: Collection<CallableMemberDescriptor>,
reportError: CheckOverrideReportStrategy
reportError: CheckOverrideReportStrategy,
kotlinTypeRefiner: KotlinTypeRefiner
) {
val propertyMemberDescriptor = if (memberDescriptor is PropertyDescriptor) memberDescriptor else null
@@ -842,10 +856,10 @@ class OverrideResolver(
val overriddenProperty = overridden.assertedCast<PropertyDescriptor> {
"$overridden is overridden by property $propertyMemberDescriptor"
}
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor, kotlinTypeRefiner)) {
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
}
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor, kotlinTypeRefiner)) {
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
}
@@ -857,7 +871,8 @@ class OverrideResolver(
private fun isReturnTypeOkForOverride(
superDescriptor: CallableDescriptor,
subDescriptor: CallableDescriptor
subDescriptor: CallableDescriptor,
kotlinTypeRefiner: KotlinTypeRefiner
): Boolean {
val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false
@@ -867,7 +882,7 @@ class OverrideResolver(
val substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE)!!
return KotlinTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType)
return NewKotlinTypeCheckerImpl(kotlinTypeRefiner).isSubtypeOf(subReturnType, substitutedSuperReturnType)
}
private fun prepareTypeSubstitutor(
@@ -322,7 +322,11 @@ public class OverridingUtil {
}
for (int i = 0; i < superValueParameters.size(); i++) {
if (!areTypesEquivalent(superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
if (!areTypesEquivalent(
kotlinTypeRefiner.refineType(superValueParameters.get(i)),
kotlinTypeRefiner.refineType(subValueParameters.get(i)),
typeChecker)
) {
return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
actual typealias Expect = String
interface Derived : Base {
override fun expectInReturnType(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Expect<!>
override fun expectInReturnType(): Expect
override fun expectInArgument(e: Expect)