Discriminate overloading expect MemberDescriptors

Issue #KT-38298
This commit is contained in:
Dmitriy Dolovov
2020-04-17 15:27:23 +07:00
parent 34ae35b2aa
commit 90e888a1b6
7 changed files with 56 additions and 23 deletions
@@ -125,11 +125,16 @@ fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): Calla
* The returned function should be called from TImpl-bridges generated for the given fake override. * The returned function should be called from TImpl-bridges generated for the given fake override.
*/ */
fun firstSuperMethodFromKotlin( fun firstSuperMethodFromKotlin(
descriptor: CallableMemberDescriptor, descriptor: CallableMemberDescriptor,
implementation: CallableMemberDescriptor implementation: CallableMemberDescriptor
): CallableMemberDescriptor? { ): CallableMemberDescriptor? {
return descriptor.overriddenDescriptors.firstOrNull { overridden -> return descriptor.overriddenDescriptors.firstOrNull { overridden ->
overridden.modality != Modality.ABSTRACT && overridden.modality != Modality.ABSTRACT &&
(overridden == implementation || OverridingUtil.overrides(overridden, implementation, overridden.module.isTypeRefinementEnabled())) (overridden == implementation || OverridingUtil.overrides(
overridden,
implementation,
overridden.module.isTypeRefinementEnabled(),
true
))
} }
} }
@@ -178,7 +178,8 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
it == overriddenDescriptor || OverridingUtil.overrides( it == overriddenDescriptor || OverridingUtil.overrides(
it, it,
overriddenDescriptor, overriddenDescriptor,
it.module.isTypeRefinementEnabled() it.module.isTypeRefinementEnabled(),
true
) )
} }
} }
@@ -135,8 +135,8 @@ open class OverloadingConflictResolver<C : Any>(
if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent( if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
me, me,
other, other,
isTypeRefinementEnabled, allowCopiesFromTheSameDeclaration = isTypeRefinementEnabled,
ignoreReturnType ignoreReturnType = ignoreReturnType
) )
) { ) {
continue@outerLoop continue@outerLoop
@@ -329,7 +329,7 @@ public abstract class ExpectedResolveData {
} }
private static void assertDescriptorsEqual(String message, DeclarationDescriptor expected, DeclarationDescriptor actual) { private static void assertDescriptorsEqual(String message, DeclarationDescriptor expected, DeclarationDescriptor actual) {
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(expected, actual, true)) { if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(expected, actual, true, true)) {
return; return;
} }
String formatted = ""; String formatted = "";
@@ -24,20 +24,26 @@ object DescriptorEquivalenceForOverrides {
fun areEquivalent( fun areEquivalent(
a: DeclarationDescriptor?, a: DeclarationDescriptor?,
b: DeclarationDescriptor?, b: DeclarationDescriptor?,
allowCopiesFromTheSameDeclaration: Boolean allowCopiesFromTheSameDeclaration: Boolean,
distinguishExpectsAndNonExpects: Boolean = true
): Boolean { ): Boolean {
return when { return when {
a is ClassDescriptor && a is ClassDescriptor && b is ClassDescriptor -> areClassesEquivalent(a, b)
b is ClassDescriptor -> areClassesEquivalent(a, b)
a is TypeParameterDescriptor && a is TypeParameterDescriptor && b is TypeParameterDescriptor -> areTypeParametersEquivalent(
b is TypeParameterDescriptor -> areTypeParametersEquivalent(a, b, allowCopiesFromTheSameDeclaration) a,
b,
allowCopiesFromTheSameDeclaration
)
a is CallableDescriptor && a is CallableDescriptor && b is CallableDescriptor -> areCallableDescriptorsEquivalent(
b is CallableDescriptor -> areCallableDescriptorsEquivalent(a, b, allowCopiesFromTheSameDeclaration) a,
b,
allowCopiesFromTheSameDeclaration = allowCopiesFromTheSameDeclaration,
distinguishExpectsAndNonExpects = distinguishExpectsAndNonExpects
)
a is PackageFragmentDescriptor && a is PackageFragmentDescriptor && b is PackageFragmentDescriptor -> (a).fqName == (b).fqName
b is PackageFragmentDescriptor -> (a).fqName == (b).fqName
else -> a == b else -> a == b
} }
@@ -72,14 +78,15 @@ object DescriptorEquivalenceForOverrides {
a: CallableDescriptor, a: CallableDescriptor,
b: CallableDescriptor, b: CallableDescriptor,
allowCopiesFromTheSameDeclaration: Boolean, allowCopiesFromTheSameDeclaration: Boolean,
distinguishExpectsAndNonExpects: Boolean = true,
ignoreReturnType: Boolean = false ignoreReturnType: Boolean = false
): Boolean { ): Boolean {
if (a == b) return true if (a == b) return true
if (a.name != b.name) return false if (a.name != b.name) return false
if (distinguishExpectsAndNonExpects && a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false
if (a.containingDeclaration == b.containingDeclaration) { if (a.containingDeclaration == b.containingDeclaration) {
if (!allowCopiesFromTheSameDeclaration) return false if (!allowCopiesFromTheSameDeclaration) return false
if (a.singleSource() != b.singleSource()) return false if (a.singleSource() != b.singleSource()) return false
if (a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false
} }
// Distinct locals are not equivalent // Distinct locals are not equivalent
@@ -126,10 +126,10 @@ public class OverridingUtil {
Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD); Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD);
CallableDescriptor me = meAndOther.component1(); CallableDescriptor me = meAndOther.component1();
CallableDescriptor other = meAndOther.component2(); CallableDescriptor other = meAndOther.component2();
if (overrides(me, other, allowDescriptorCopies)) { if (overrides(me, other, allowDescriptorCopies, true)) {
iterator.remove(); iterator.remove();
} }
else if (overrides(other, me, allowDescriptorCopies)) { else if (overrides(other, me, allowDescriptorCopies, true)) {
continue outerLoop; continue outerLoop;
} }
} }
@@ -145,7 +145,10 @@ public class OverridingUtil {
* @return whether f overrides g * @return whether f overrides g
*/ */
public static <D extends CallableDescriptor> boolean overrides( public static <D extends CallableDescriptor> boolean overrides(
@NotNull D f, @NotNull D g, boolean allowDeclarationCopies @NotNull D f,
@NotNull D g,
boolean allowDeclarationCopies,
boolean distinguishExpectsAndNonExpects
) { ) {
// In a multi-module project different "copies" of the same class may be present in different libraries, // In a multi-module project different "copies" of the same class may be present in different libraries,
// that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides). // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).
@@ -155,11 +158,27 @@ public class OverridingUtil {
// we'll be getting sets of members that do not override each other, but are structurally equivalent. // we'll be getting sets of members that do not override each other, but are structurally equivalent.
// As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
// Note that this is needed for the usage of this function in the IDE code // Note that this is needed for the usage of this function in the IDE code
if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal(), allowDeclarationCopies)) return true; if (!f.equals(g)
&& DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
f.getOriginal(),
g.getOriginal(),
allowDeclarationCopies,
distinguishExpectsAndNonExpects
)
) {
return true;
}
CallableDescriptor originalG = g.getOriginal(); CallableDescriptor originalG = g.getOriginal();
for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) { for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) {
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction, allowDeclarationCopies)) return true; if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
originalG,
overriddenFunction,
allowDeclarationCopies,
distinguishExpectsAndNonExpects
)) {
return true;
}
} }
return false; return false;
} }
@@ -267,7 +267,8 @@ fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boole
usageDescriptor != null && OverridingUtil.overrides( usageDescriptor != null && OverridingUtil.overrides(
usageDescriptor, usageDescriptor,
targetDescriptor, targetDescriptor,
usageDescriptor.module.isTypeRefinementEnabled() usageDescriptor.module.isTypeRefinementEnabled(),
false // don't distinguish between expect and non-expect callable descriptors, KT-38298, KT-38589
) )
} }
is PsiMethod -> { is PsiMethod -> {