Refine types of type parameters before checking their equality in OverridingUtil
This commit is contained in:
@@ -38,9 +38,12 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractFakeOverride
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractFakeOverride
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
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.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
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.types.refinement.TypeRefinement
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -74,7 +77,7 @@ class OverrideResolver(
|
|||||||
|
|
||||||
val inheritedMemberErrors = CollectErrorInformationForInheritedMembersStrategy(klass, classDescriptor)
|
val inheritedMemberErrors = CollectErrorInformationForInheritedMembersStrategy(klass, classDescriptor)
|
||||||
|
|
||||||
checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors)
|
checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors, kotlinTypeRefiner)
|
||||||
inheritedMemberErrors.doReportErrors()
|
inheritedMemberErrors.doReportErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,7 +381,7 @@ class OverrideResolver(
|
|||||||
override fun varOverriddenByVal(overriding: CallableMemberDescriptor, overridden: CallableMemberDescriptor) {
|
override fun varOverriddenByVal(overriding: CallableMemberDescriptor, overridden: CallableMemberDescriptor) {
|
||||||
throw IllegalStateException("Component functions are not properties")
|
throw IllegalStateException("Component functions are not properties")
|
||||||
}
|
}
|
||||||
})
|
}, kotlinTypeRefiner)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOverrideForCopyFunction(copyFunction: CallableMemberDescriptor) {
|
private fun checkOverrideForCopyFunction(copyFunction: CallableMemberDescriptor) {
|
||||||
@@ -561,18 +564,25 @@ class OverrideResolver(
|
|||||||
|
|
||||||
fun getMissingImplementations(classDescriptor: ClassDescriptor): Set<CallableMemberDescriptor> {
|
fun getMissingImplementations(classDescriptor: ClassDescriptor): Set<CallableMemberDescriptor> {
|
||||||
val collector = CollectMissingImplementationsStrategy()
|
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
|
return collector.shouldImplement
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkInheritedAndDelegatedSignatures(
|
private fun checkInheritedAndDelegatedSignatures(
|
||||||
classDescriptor: ClassDescriptor,
|
classDescriptor: ClassDescriptor,
|
||||||
inheritedReportStrategy: CheckInheritedSignaturesReportStrategy,
|
inheritedReportStrategy: CheckInheritedSignaturesReportStrategy,
|
||||||
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?
|
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
) {
|
) {
|
||||||
for (member in DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)) {
|
for (member in DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)) {
|
||||||
if (member is CallableMemberDescriptor) {
|
if (member is CallableMemberDescriptor) {
|
||||||
checkInheritedAndDelegatedSignatures(member, inheritedReportStrategy, overrideReportStrategyForDelegates)
|
checkInheritedAndDelegatedSignatures(member, inheritedReportStrategy, overrideReportStrategyForDelegates, kotlinTypeRefiner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -580,7 +590,8 @@ class OverrideResolver(
|
|||||||
private fun checkInheritedAndDelegatedSignatures(
|
private fun checkInheritedAndDelegatedSignatures(
|
||||||
descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
reportingStrategy: CheckInheritedSignaturesReportStrategy,
|
reportingStrategy: CheckInheritedSignaturesReportStrategy,
|
||||||
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?
|
overrideReportStrategyForDelegates: CheckOverrideReportStrategy?,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
) {
|
) {
|
||||||
val kind = descriptor.kind
|
val kind = descriptor.kind
|
||||||
if (kind != FAKE_OVERRIDE && kind != DELEGATION) return
|
if (kind != FAKE_OVERRIDE && kind != DELEGATION) return
|
||||||
@@ -606,10 +617,10 @@ class OverrideResolver(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy)
|
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy, kotlinTypeRefiner)
|
||||||
|
|
||||||
if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
|
if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
|
||||||
checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates)
|
checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates, kotlinTypeRefiner)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind != DELEGATION) {
|
if (kind != DELEGATION) {
|
||||||
@@ -632,7 +643,7 @@ class OverrideResolver(
|
|||||||
1 ->
|
1 ->
|
||||||
if (kind != DELEGATION) {
|
if (kind != DELEGATION) {
|
||||||
val implementation = concreteOverridden.first()
|
val implementation = concreteOverridden.first()
|
||||||
collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementation).forEach {
|
collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementation, kotlinTypeRefiner).forEach {
|
||||||
reportingStrategy.abstractMemberWithMoreSpecificType(it, implementation)
|
reportingStrategy.abstractMemberWithMoreSpecificType(it, implementation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -703,9 +714,10 @@ class OverrideResolver(
|
|||||||
|
|
||||||
private fun collectAbstractMethodsWithMoreSpecificReturnType(
|
private fun collectAbstractMethodsWithMoreSpecificReturnType(
|
||||||
abstractOverridden: List<CallableMemberDescriptor>,
|
abstractOverridden: List<CallableMemberDescriptor>,
|
||||||
implementation: CallableMemberDescriptor
|
implementation: CallableMemberDescriptor,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
): List<CallableMemberDescriptor> =
|
): List<CallableMemberDescriptor> =
|
||||||
abstractOverridden.filter { abstractMember -> !isReturnTypeOkForOverride(abstractMember, implementation) }
|
abstractOverridden.filter { abstractMember -> !isReturnTypeOkForOverride(abstractMember, implementation, kotlinTypeRefiner) }
|
||||||
|
|
||||||
private fun getRelevantDirectlyOverridden(
|
private fun getRelevantDirectlyOverridden(
|
||||||
overriddenByParent: MutableMap<CallableMemberDescriptor, Set<CallableMemberDescriptor>>,
|
overriddenByParent: MutableMap<CallableMemberDescriptor, Set<CallableMemberDescriptor>>,
|
||||||
@@ -778,7 +790,8 @@ class OverrideResolver(
|
|||||||
private fun checkInheritedDescriptorsGroup(
|
private fun checkInheritedDescriptorsGroup(
|
||||||
descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
overriddenDescriptors: Collection<CallableMemberDescriptor>,
|
overriddenDescriptors: Collection<CallableMemberDescriptor>,
|
||||||
reportingStrategy: CheckInheritedSignaturesReportStrategy
|
reportingStrategy: CheckInheritedSignaturesReportStrategy,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
) {
|
) {
|
||||||
if (overriddenDescriptors.size <= 1) return
|
if (overriddenDescriptors.size <= 1) return
|
||||||
|
|
||||||
@@ -792,7 +805,7 @@ class OverrideResolver(
|
|||||||
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor)
|
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor)) {
|
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor, kotlinTypeRefiner)) {
|
||||||
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
|
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -806,7 +819,7 @@ class OverrideResolver(
|
|||||||
) {
|
) {
|
||||||
val overriddenDescriptors = declared.overriddenDescriptors
|
val overriddenDescriptors = declared.overriddenDescriptors
|
||||||
|
|
||||||
checkOverridesForMember(declared, overriddenDescriptors, reportError)
|
checkOverridesForMember(declared, overriddenDescriptors, reportError, kotlinTypeRefiner)
|
||||||
|
|
||||||
if (overriddenDescriptors.isEmpty()) {
|
if (overriddenDescriptors.isEmpty()) {
|
||||||
val containingDeclaration = declared.containingDeclaration
|
val containingDeclaration = declared.containingDeclaration
|
||||||
@@ -829,7 +842,8 @@ class OverrideResolver(
|
|||||||
private fun checkOverridesForMember(
|
private fun checkOverridesForMember(
|
||||||
memberDescriptor: CallableMemberDescriptor,
|
memberDescriptor: CallableMemberDescriptor,
|
||||||
overriddenDescriptors: Collection<CallableMemberDescriptor>,
|
overriddenDescriptors: Collection<CallableMemberDescriptor>,
|
||||||
reportError: CheckOverrideReportStrategy
|
reportError: CheckOverrideReportStrategy,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
) {
|
) {
|
||||||
val propertyMemberDescriptor = if (memberDescriptor is PropertyDescriptor) memberDescriptor else null
|
val propertyMemberDescriptor = if (memberDescriptor is PropertyDescriptor) memberDescriptor else null
|
||||||
|
|
||||||
@@ -842,10 +856,10 @@ class OverrideResolver(
|
|||||||
val overriddenProperty = overridden.assertedCast<PropertyDescriptor> {
|
val overriddenProperty = overridden.assertedCast<PropertyDescriptor> {
|
||||||
"$overridden is overridden by property $propertyMemberDescriptor"
|
"$overridden is overridden by property $propertyMemberDescriptor"
|
||||||
}
|
}
|
||||||
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
|
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor, kotlinTypeRefiner)) {
|
||||||
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
|
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
|
||||||
}
|
}
|
||||||
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
|
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor, kotlinTypeRefiner)) {
|
||||||
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
|
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,7 +871,8 @@ class OverrideResolver(
|
|||||||
|
|
||||||
private fun isReturnTypeOkForOverride(
|
private fun isReturnTypeOkForOverride(
|
||||||
superDescriptor: CallableDescriptor,
|
superDescriptor: CallableDescriptor,
|
||||||
subDescriptor: CallableDescriptor
|
subDescriptor: CallableDescriptor,
|
||||||
|
kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false
|
val typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor) ?: return false
|
||||||
|
|
||||||
@@ -867,7 +882,7 @@ class OverrideResolver(
|
|||||||
|
|
||||||
val substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE)!!
|
val substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE)!!
|
||||||
|
|
||||||
return KotlinTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType)
|
return NewKotlinTypeCheckerImpl(kotlinTypeRefiner).isSubtypeOf(subReturnType, substitutedSuperReturnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareTypeSubstitutor(
|
private fun prepareTypeSubstitutor(
|
||||||
|
|||||||
@@ -322,7 +322,11 @@ public class OverridingUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < superValueParameters.size(); i++) {
|
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");
|
return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
actual typealias Expect = String
|
actual typealias Expect = String
|
||||||
|
|
||||||
interface Derived : Base {
|
interface Derived : Base {
|
||||||
override fun expectInReturnType(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Expect<!>
|
override fun expectInReturnType(): Expect
|
||||||
|
|
||||||
override fun expectInArgument(e: Expect)
|
override fun expectInArgument(e: Expect)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user