Parametrize behavior of DescriptorEquivalenceForOverrides::areCallableDescriptorsEquivalent

The changes introduced 471134d31e are only needed
for the case of HMPP project while for other cases it might break the behavior
a bit like in KT-34027

See org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver#filterOutEquivalentCalls

Before 471134d we were comparing
"fun foo(x: String)" with "[substituted] fun foo(x: String)"
and areCallableDescriptorsEquivalent returned false for such case.
Thus, both overrides were left in the resulting set.

After 471134d, those two descriptors
becamed considered as equal thus having a possibility to remove any of them.

The problem is that "areCallableDescriptorsEquivalent" has kind of
unclear contract. Effectively it checks whether two descriptors match
to the same declaration

But straightforward fixing of this exact call-site (using original descriptors)
doesn't help: behavior might change in a very subtle way (see org.jetbrains.kotlin.spec.checkers.DiagnosticsTestSpecGenerated.NotLinked.Dfa.Pos#test72)

So, the main idea is changing the contract for areCallableDescriptorsEquivalent
only when project is HMPP one.

^KT-34027 In Progress
This commit is contained in:
Denis Zharkov
2019-09-30 15:54:46 +03:00
parent 08794d17a0
commit 67410f7a57
11 changed files with 76 additions and 26 deletions
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.descriptorUtil.module
fun <Signature> generateBridgesForFunctionDescriptor( fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
@@ -128,6 +130,6 @@ fun firstSuperMethodFromKotlin(
): 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 == implementation || OverridingUtil.overrides(overridden, implementation, overridden.module.isTypeRefinementEnabled()))
} }
} }
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.isDynamic
@@ -172,7 +174,13 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
// this is the actual member of delegateExpressionType that we are delegating to // this is the actual member of delegateExpressionType that we are delegating to
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) + (scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES)) scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) } .firstOrNull {
it == overriddenDescriptor || OverridingUtil.overrides(
it,
overriddenDescriptor,
it.module.isTypeRefinementEnabled()
)
}
} }
actualDelegates.firstOrNull() actualDelegates.firstOrNull()
@@ -61,7 +61,10 @@ interface IdentifierInfo {
get() = kind == STABLE_VALUE get() = kind == STABLE_VALUE
override fun equals(other: Any?) = override fun equals(other: Any?) =
other is Variable && DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(variable, other.variable) other is Variable &&
DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
variable, other.variable, allowCopiesFromTheSameDeclaration = true
)
override fun hashCode() = variable.name.hashCode() * 31 + variable.containingDeclaration.original.hashCode() override fun hashCode() = variable.name.hashCode() * 31 + variable.containingDeclaration.original.hashCode()
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
@@ -44,6 +45,8 @@ open class OverloadingConflictResolver<C : Any>(
private val hasSAMConversion: ((C) -> Boolean)? private val hasSAMConversion: ((C) -> Boolean)?
) { ) {
private val isTypeRefinementEnabled by lazy { module.isTypeRefinementEnabled() }
private val resolvedCallHashingStrategy = object : TObjectHashingStrategy<C> { private val resolvedCallHashingStrategy = object : TObjectHashingStrategy<C> {
override fun equals(call1: C?, call2: C?): Boolean = override fun equals(call1: C?, call2: C?): Boolean =
if (call1 != null && call2 != null) if (call1 != null && call2 != null)
@@ -72,7 +75,10 @@ open class OverloadingConflictResolver<C : Any>(
} }
val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates) val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates)
val noOverrides = OverridingUtil.filterOverrides(noEquivalentCalls) { a, b -> val noOverrides = OverridingUtil.filterOverrides(
noEquivalentCalls,
isTypeRefinementEnabled
) { a, b ->
val aDescriptor = a.resultingDescriptor val aDescriptor = a.resultingDescriptor
val bDescriptor = b.resultingDescriptor val bDescriptor = b.resultingDescriptor
// Here we'd like to handle situation when we have two synthetic descriptors as in syntheticSAMExtensions.kt // Here we'd like to handle situation when we have two synthetic descriptors as in syntheticSAMExtensions.kt
@@ -121,7 +127,13 @@ open class OverloadingConflictResolver<C : Any>(
val me = meD.resultingDescriptor val me = meD.resultingDescriptor
val other = otherD.resultingDescriptor val other = otherD.resultingDescriptor
val ignoreReturnType = isFromSources(me) != isFromSources(other) val ignoreReturnType = isFromSources(me) != isFromSources(other)
if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(me, other, ignoreReturnType)) { if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
me,
other,
isTypeRefinementEnabled,
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)) { if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(expected, actual, true)) {
return; return;
} }
String formatted = ""; String formatted = "";
@@ -21,16 +21,20 @@ import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
object DescriptorEquivalenceForOverrides { object DescriptorEquivalenceForOverrides {
fun areEquivalent(a: DeclarationDescriptor?, b: DeclarationDescriptor?): Boolean { fun areEquivalent(
a: DeclarationDescriptor?,
b: DeclarationDescriptor?,
allowCopiesFromTheSameDeclaration: 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(a, b) b is TypeParameterDescriptor -> areTypeParametersEquivalent(a, b, allowCopiesFromTheSameDeclaration)
a is CallableDescriptor && a is CallableDescriptor &&
b is CallableDescriptor -> areCallableDescriptorsEquivalent(a, b) b is CallableDescriptor -> areCallableDescriptorsEquivalent(a, b, allowCopiesFromTheSameDeclaration)
a is PackageFragmentDescriptor && a is PackageFragmentDescriptor &&
b is PackageFragmentDescriptor -> (a).fqName == (b).fqName b is PackageFragmentDescriptor -> (a).fqName == (b).fqName
@@ -47,12 +51,13 @@ object DescriptorEquivalenceForOverrides {
private fun areTypeParametersEquivalent( private fun areTypeParametersEquivalent(
a: TypeParameterDescriptor, a: TypeParameterDescriptor,
b: TypeParameterDescriptor, b: TypeParameterDescriptor,
allowCopiesFromTheSameDeclaration: Boolean,
equivalentCallables: (DeclarationDescriptor?, DeclarationDescriptor?) -> Boolean = { _, _ -> false } equivalentCallables: (DeclarationDescriptor?, DeclarationDescriptor?) -> Boolean = { _, _ -> false }
): Boolean { ): Boolean {
if (a == b) return true if (a == b) return true
if (a.containingDeclaration == b.containingDeclaration) return false if (a.containingDeclaration == b.containingDeclaration) return false
if (!ownersEquivalent(a, b, equivalentCallables)) return false if (!ownersEquivalent(a, b, equivalentCallables, allowCopiesFromTheSameDeclaration)) return false
return a.index == b.index // We ignore type parameter names return a.index == b.index // We ignore type parameter names
} }
@@ -66,11 +71,13 @@ object DescriptorEquivalenceForOverrides {
fun areCallableDescriptorsEquivalent( fun areCallableDescriptorsEquivalent(
a: CallableDescriptor, a: CallableDescriptor,
b: CallableDescriptor, b: CallableDescriptor,
allowCopiesFromTheSameDeclaration: Boolean,
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 (a.containingDeclaration == b.containingDeclaration) { if (a.containingDeclaration == b.containingDeclaration) {
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 if (a is MemberDescriptor && b is MemberDescriptor && a.isExpect != b.isExpect) return false
} }
@@ -78,7 +85,7 @@ object DescriptorEquivalenceForOverrides {
// Distinct locals are not equivalent // Distinct locals are not equivalent
if (DescriptorUtils.isLocal(a) || DescriptorUtils.isLocal(b)) return false if (DescriptorUtils.isLocal(a) || DescriptorUtils.isLocal(b)) return false
if (!ownersEquivalent(a, b, { _, _ -> false })) return false if (!ownersEquivalent(a, b, { _, _ -> false }, allowCopiesFromTheSameDeclaration)) return false
val overridingUtil = OverridingUtil.createWithEqualityAxioms eq@{ c1, c2 -> val overridingUtil = OverridingUtil.createWithEqualityAxioms eq@{ c1, c2 ->
if (c1 == c2) return@eq true if (c1 == c2) return@eq true
@@ -88,7 +95,7 @@ object DescriptorEquivalenceForOverrides {
if (d1 !is TypeParameterDescriptor || d2 !is TypeParameterDescriptor) return@eq false if (d1 !is TypeParameterDescriptor || d2 !is TypeParameterDescriptor) return@eq false
areTypeParametersEquivalent(d1, d2, { x, y -> x == a && y == b }) areTypeParametersEquivalent(d1, d2, allowCopiesFromTheSameDeclaration) { x, y -> x == a && y == b }
} }
return overridingUtil.isOverridableBy(a, b, null, !ignoreReturnType).result == OverrideCompatibilityInfo.Result.OVERRIDABLE return overridingUtil.isOverridableBy(a, b, null, !ignoreReturnType).result == OverrideCompatibilityInfo.Result.OVERRIDABLE
@@ -99,7 +106,8 @@ object DescriptorEquivalenceForOverrides {
private fun ownersEquivalent( private fun ownersEquivalent(
a: DeclarationDescriptor, a: DeclarationDescriptor,
b: DeclarationDescriptor, b: DeclarationDescriptor,
equivalentCallables: (DeclarationDescriptor?, DeclarationDescriptor?) -> Boolean equivalentCallables: (DeclarationDescriptor?, DeclarationDescriptor?) -> Boolean,
allowCopiesFromTheSameDeclaration: Boolean
): Boolean { ): Boolean {
val aOwner = a.containingDeclaration val aOwner = a.containingDeclaration
val bOwner = b.containingDeclaration val bOwner = b.containingDeclaration
@@ -109,7 +117,7 @@ object DescriptorEquivalenceForOverrides {
return if (aOwner is CallableMemberDescriptor || bOwner is CallableMemberDescriptor) { return if (aOwner is CallableMemberDescriptor || bOwner is CallableMemberDescriptor) {
equivalentCallables(aOwner, bOwner) equivalentCallables(aOwner, bOwner)
} else { } else {
areEquivalent(aOwner, bOwner) areEquivalent(aOwner, bOwner, allowCopiesFromTheSameDeclaration)
} }
} }
@@ -446,4 +446,7 @@ fun DeclarationDescriptor.isPrimaryConstructorOfInlineClass(): Boolean =
this is ConstructorDescriptor && this.isPrimary && this.constructedClass.isInline this is ConstructorDescriptor && this.isPrimary && this.constructedClass.isInline
@TypeRefinement @TypeRefinement
fun ModuleDescriptor.getKotlinTypeRefiner(): KotlinTypeRefiner = getCapability(REFINER_CAPABILITY)?.value ?: KotlinTypeRefiner.Default fun ModuleDescriptor.getKotlinTypeRefiner(): KotlinTypeRefiner = getCapability(REFINER_CAPABILITY)?.value ?: KotlinTypeRefiner.Default
@UseExperimental(TypeRefinement::class)
fun ModuleDescriptor.isTypeRefinementEnabled(): Boolean = getCapability(REFINER_CAPABILITY)?.value != null
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.FlexibleTypesKt; import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.KotlinTypeKt; import org.jetbrains.kotlin.types.KotlinTypeKt;
@@ -92,7 +93,11 @@ public class OverridingUtil {
*/ */
@NotNull @NotNull
public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) { public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
return filterOverrides(candidateSet, new Function2<D, D, Pair<CallableDescriptor, CallableDescriptor>>() { boolean allowDescriptorCopies = !candidateSet.isEmpty() &&
DescriptorUtilsKt
.isTypeRefinementEnabled(DescriptorUtilsKt.getModule(candidateSet.iterator().next()));
return filterOverrides(candidateSet, allowDescriptorCopies, new Function2<D, D, Pair<CallableDescriptor, CallableDescriptor>>() {
@Override @Override
public Pair<CallableDescriptor, CallableDescriptor> invoke(D a, D b) { public Pair<CallableDescriptor, CallableDescriptor> invoke(D a, D b) {
return new Pair<CallableDescriptor, CallableDescriptor>(a, b); return new Pair<CallableDescriptor, CallableDescriptor>(a, b);
@@ -103,6 +108,7 @@ public class OverridingUtil {
@NotNull @NotNull
public static <D> Set<D> filterOverrides( public static <D> Set<D> filterOverrides(
@NotNull Set<D> candidateSet, @NotNull Set<D> candidateSet,
boolean allowDescriptorCopies,
@NotNull Function2<? super D, ? super D, Pair<CallableDescriptor, CallableDescriptor>> transformFirst @NotNull Function2<? super D, ? super D, Pair<CallableDescriptor, CallableDescriptor>> transformFirst
) { ) {
if (candidateSet.size() <= 1) return candidateSet; if (candidateSet.size() <= 1) return candidateSet;
@@ -115,10 +121,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)) { if (overrides(me, other, allowDescriptorCopies)) {
iterator.remove(); iterator.remove();
} }
else if (overrides(other, me)) { else if (overrides(other, me, allowDescriptorCopies)) {
continue outerLoop; continue outerLoop;
} }
} }
@@ -133,7 +139,9 @@ public class OverridingUtil {
/** /**
* @return whether f overrides g * @return whether f overrides g
*/ */
public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) { public static <D extends CallableDescriptor> boolean overrides(
@NotNull D f, @NotNull D g, boolean allowDeclarationCopies
) {
// 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).
@@ -142,11 +150,11 @@ 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())) return true; if (!f.equals(g) && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(f.getOriginal(), g.getOriginal(), allowDeclarationCopies)) 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)) return true; if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction, allowDeclarationCopies)) return true;
} }
return false; return false;
} }
@@ -124,7 +124,7 @@ class KotlinPsiUnifier(
} }
private fun matchDescriptors(d1: DeclarationDescriptor?, d2: DeclarationDescriptor?): Boolean { private fun matchDescriptors(d1: DeclarationDescriptor?, d2: DeclarationDescriptor?): Boolean {
if (DescriptorEquivalenceForOverrides.areEquivalent(d1, d2)) return true if (DescriptorEquivalenceForOverrides.areEquivalent(d1, d2, allowCopiesFromTheSameDeclaration = true)) return true
if (d2 in declarationPatternsToTargets[d1] || d1 in declarationPatternsToTargets[d2]) return true if (d2 in declarationPatternsToTargets[d1] || d1 in declarationPatternsToTargets[d2]) return true
if (d1 == null || d2 == null) return false if (d1 == null || d2 == null) return false
@@ -46,6 +46,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
val KtDeclaration.descriptor: DeclarationDescriptor? val KtDeclaration.descriptor: DeclarationDescriptor?
@@ -265,7 +267,11 @@ fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boole
when (it) { when (it) {
is KtDeclaration -> { is KtDeclaration -> {
val usageDescriptor = toDescriptor(it) val usageDescriptor = toDescriptor(it)
usageDescriptor != null && OverridingUtil.overrides(usageDescriptor, targetDescriptor) usageDescriptor != null && OverridingUtil.overrides(
usageDescriptor,
targetDescriptor,
usageDescriptor.module.isTypeRefinementEnabled()
)
} }
is PsiMethod -> { is PsiMethod -> {
declaration.toLightMethods().any { superMethod -> MethodSignatureUtil.isSuperMethod(superMethod, it) } declaration.toLightMethods().any { superMethod -> MethodSignatureUtil.isSuperMethod(superMethod, it) }
@@ -33,8 +33,6 @@ import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.refinement.TypeRefinement
class JsNameClashChecker( class JsNameClashChecker(
private val nameSuggestion: NameSuggestion, private val nameSuggestion: NameSuggestion,
@@ -125,7 +123,9 @@ class JsNameClashChecker(
} else { } else {
// If refinement is enabled, we can get duplicate descriptors for one and the same members (as refinement re-creates // If refinement is enabled, we can get duplicate descriptors for one and the same members (as refinement re-creates
// descriptors), so, in this case, we have to compare descriptors structurally // descriptors), so, in this case, we have to compare descriptors structurally
DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(existing, overrideDescriptor) DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
existing, overrideDescriptor, allowCopiesFromTheSameDeclaration = true
)
} }
} }