Skip to content

Commit 90e888a

Browse files
committed
Discriminate overloading expect MemberDescriptors
Issue #KT-38298
1 parent 34ae35b commit 90e888a

File tree

7 files changed

+56
-23
lines changed

7 files changed

+56
-23
lines changed

compiler/backend-common/src/org/jetbrains/kotlin/backend/common/bridges/impl.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,16 @@ fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): Calla
125125
* The returned function should be called from TImpl-bridges generated for the given fake override.
126126
*/
127127
fun firstSuperMethodFromKotlin(
128-
descriptor: CallableMemberDescriptor,
129-
implementation: CallableMemberDescriptor
128+
descriptor: CallableMemberDescriptor,
129+
implementation: CallableMemberDescriptor
130130
): CallableMemberDescriptor? {
131131
return descriptor.overriddenDescriptors.firstOrNull { overridden ->
132132
overridden.modality != Modality.ABSTRACT &&
133-
(overridden == implementation || OverridingUtil.overrides(overridden, implementation, overridden.module.isTypeRefinementEnabled()))
133+
(overridden == implementation || OverridingUtil.overrides(
134+
overridden,
135+
implementation,
136+
overridden.module.isTypeRefinementEnabled(),
137+
true
138+
))
134139
}
135140
}

compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
178178
it == overriddenDescriptor || OverridingUtil.overrides(
179179
it,
180180
overriddenDescriptor,
181-
it.module.isTypeRefinementEnabled()
181+
it.module.isTypeRefinementEnabled(),
182+
true
182183
)
183184
}
184185
}

compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ open class OverloadingConflictResolver<C : Any>(
135135
if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
136136
me,
137137
other,
138-
isTypeRefinementEnabled,
139-
ignoreReturnType
138+
allowCopiesFromTheSameDeclaration = isTypeRefinementEnabled,
139+
ignoreReturnType = ignoreReturnType
140140
)
141141
) {
142142
continue@outerLoop

compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveData.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ private static void assertTypeConstructorEquals(String message, TypeConstructor
329329
}
330330

331331
private static void assertDescriptorsEqual(String message, DeclarationDescriptor expected, DeclarationDescriptor actual) {
332-
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(expected, actual, true)) {
332+
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(expected, actual, true, true)) {
333333
return;
334334
}
335335
String formatted = "";

core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorEquivalenceForOverrides.kt

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,26 @@ object DescriptorEquivalenceForOverrides {
2424
fun areEquivalent(
2525
a: DeclarationDescriptor?,
2626
b: DeclarationDescriptor?,
27-
allowCopiesFromTheSameDeclaration: Boolean
27+
allowCopiesFromTheSameDeclaration: Boolean,
28+
distinguishExpectsAndNonExpects: Boolean = true
2829
): Boolean {
2930
return when {
30-
a is ClassDescriptor &&
31-
b is ClassDescriptor -> areClassesEquivalent(a, b)
31+
a is ClassDescriptor && b is ClassDescriptor -> areClassesEquivalent(a, b)
3232

33-
a is TypeParameterDescriptor &&
34-
b is TypeParameterDescriptor -> areTypeParametersEquivalent(a, b, allowCopiesFromTheSameDeclaration)
33+
a is TypeParameterDescriptor && b is TypeParameterDescriptor -> areTypeParametersEquivalent(
34+
a,
35+
b,
36+
allowCopiesFromTheSameDeclaration
37+
)
3538

36-
a is CallableDescriptor &&
37-
b is CallableDescriptor -> areCallableDescriptorsEquivalent(a, b, allowCopiesFromTheSameDeclaration)
39+
a is CallableDescriptor && b is CallableDescriptor -> areCallableDescriptorsEquivalent(
40+
a,
41+
b,
42+
allowCopiesFromTheSameDeclaration = allowCopiesFromTheSameDeclaration,
43+
distinguishExpectsAndNonExpects = distinguishExpectsAndNonExpects
44+
)
3845

39-
a is PackageFragmentDescriptor &&
40-
b is PackageFragmentDescriptor -> (a).fqName == (b).fqName
46+
a is PackageFragmentDescriptor && b is PackageFragmentDescriptor -> (a).fqName == (b).fqName
4147

4248
else -> a == b
4349
}
@@ -72,14 +78,15 @@ object DescriptorEquivalenceForOverrides {
7278
a: CallableDescriptor,
7379
b: CallableDescriptor,
7480
allowCopiesFromTheSameDeclaration: Boolean,
81+
distinguishExpectsAndNonExpects: Boolean = true,
7582
ignoreReturnType: Boolean = false
7683
): Boolean {
7784
if (a == b) return true
7885
if (a.name != b.name) return false
86+
if (distinguishExpectsAndNonExpects && a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false
7987
if (a.containingDeclaration == b.containingDeclaration) {
8088
if (!allowCopiesFromTheSameDeclaration) return false
8189
if (a.singleSource() != b.singleSource()) return false
82-
if (a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false
8390
}
8491

8592
// Distinct locals are not equivalent

core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,10 @@ public static <D> Set<D> filterOverrides(
126126
Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD);
127127
CallableDescriptor me = meAndOther.component1();
128128
CallableDescriptor other = meAndOther.component2();
129-
if (overrides(me, other, allowDescriptorCopies)) {
129+
if (overrides(me, other, allowDescriptorCopies, true)) {
130130
iterator.remove();
131131
}
132-
else if (overrides(other, me, allowDescriptorCopies)) {
132+
else if (overrides(other, me, allowDescriptorCopies, true)) {
133133
continue outerLoop;
134134
}
135135
}
@@ -145,7 +145,10 @@ else if (overrides(other, me, allowDescriptorCopies)) {
145145
* @return whether f overrides g
146146
*/
147147
public static <D extends CallableDescriptor> boolean overrides(
148-
@NotNull D f, @NotNull D g, boolean allowDeclarationCopies
148+
@NotNull D f,
149+
@NotNull D g,
150+
boolean allowDeclarationCopies,
151+
boolean distinguishExpectsAndNonExpects
149152
) {
150153
// In a multi-module project different "copies" of the same class may be present in different libraries,
151154
// that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).
@@ -155,11 +158,27 @@ public static <D extends CallableDescriptor> boolean overrides(
155158
// we'll be getting sets of members that do not override each other, but are structurally equivalent.
156159
// As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
157160
// Note that this is needed for the usage of this function in the IDE code
158-
if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal(), allowDeclarationCopies)) return true;
161+
if (!f.equals(g)
162+
&& DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
163+
f.getOriginal(),
164+
g.getOriginal(),
165+
allowDeclarationCopies,
166+
distinguishExpectsAndNonExpects
167+
)
168+
) {
169+
return true;
170+
}
159171

160172
CallableDescriptor originalG = g.getOriginal();
161173
for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) {
162-
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction, allowDeclarationCopies)) return true;
174+
if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
175+
originalG,
176+
overriddenFunction,
177+
allowDeclarationCopies,
178+
distinguishExpectsAndNonExpects
179+
)) {
180+
return true;
181+
}
163182
}
164183
return false;
165184
}

idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boole
267267
usageDescriptor != null && OverridingUtil.overrides(
268268
usageDescriptor,
269269
targetDescriptor,
270-
usageDescriptor.module.isTypeRefinementEnabled()
270+
usageDescriptor.module.isTypeRefinementEnabled(),
271+
false // don't distinguish between expect and non-expect callable descriptors, KT-38298, KT-38589
271272
)
272273
}
273274
is PsiMethod -> {

0 commit comments

Comments
 (0)