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
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
import org.jetbrains.kotlin.resolve.OverridingUtil
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.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -44,6 +45,8 @@ open class OverloadingConflictResolver<C : Any>(
private val hasSAMConversion: ((C) -> Boolean)?
) {
private val isTypeRefinementEnabled by lazy { module.isTypeRefinementEnabled() }
private val resolvedCallHashingStrategy = object : TObjectHashingStrategy<C> {
override fun equals(call1: C?, call2: C?): Boolean =
if (call1 != null && call2 != null)
@@ -72,7 +75,10 @@ open class OverloadingConflictResolver<C : Any>(
}
val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates)
val noOverrides = OverridingUtil.filterOverrides(noEquivalentCalls) { a, b ->
val noOverrides = OverridingUtil.filterOverrides(
noEquivalentCalls,
isTypeRefinementEnabled
) { a, b ->
val aDescriptor = a.resultingDescriptor
val bDescriptor = b.resultingDescriptor
// 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 other = otherD.resultingDescriptor
val ignoreReturnType = isFromSources(me) != isFromSources(other)
if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(me, other, ignoreReturnType)) {
if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(
me,
other,
isTypeRefinementEnabled,
ignoreReturnType
)
) {
continue@outerLoop
}
}