From f91db5f0b810fcbf38cd7c9caca5243b1a8f9ad2 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 30 Sep 2019 17:18:43 +0300 Subject: [PATCH] Restore correct overloads ambiguity accidentally removed in 1.3.60 This problem is only relevant when isTypeRefinementEnabled == true (HMPP projects) Ambiguity accidentally was removed after 471134d There, for areCallableDescriptorsEquivalent we stopped assuming as impossible a situation of having identity-different descriptors in the same containing declaraton that still might be considered equal So, 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 some of the usages expect that it also makes sure that descriptors have the same substitution (see org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo.Variable#equals) So, the straight solution is using original descriptors for the cases where we need to make sure that descriptors relates to actually different declarations ^KT-34027 Fixed --- .../fir/FirDiagnosticsSmokeTestGenerated.java | 5 +++++ .../results/OverloadingConflictResolver.kt | 6 ++++-- .../resolve/overloadConflicts/genericClash.kt | 19 +++++++++++++++++++ .../overloadConflicts/genericClash.txt | 15 +++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 +++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 +++++ .../common/common.kt | 6 ++++++ .../dependencies.txt | 5 +++++ .../js/js.kt | 8 ++++++++ .../MultiplatformAnalysisTestGenerated.java | 5 +++++ 10 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt create mode 100644 compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.txt create mode 100644 idea/testData/multiplatform/correctOverloadResolutionAmbiguity/common/common.kt create mode 100644 idea/testData/multiplatform/correctOverloadResolutionAmbiguity/dependencies.txt create mode 100644 idea/testData/multiplatform/correctOverloadResolutionAmbiguity/js/js.kt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index f28c73c9a11..5aa753a86d3 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -18088,6 +18088,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt"); } + @TestMetadata("genericClash.kt") + public void testGenericClash() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt"); + } + @TestMetadata("genericWithProjection.kt") public void testGenericWithProjection() throws Exception { runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericWithProjection.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt index 12d95bd8dd8..1cf2299a93e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt @@ -124,8 +124,8 @@ open class OverloadingConflictResolver( val result = LinkedHashSet() outerLoop@ for (meD in fromSourcesGoesFirst) { for (otherD in result) { - val me = meD.resultingDescriptor - val other = otherD.resultingDescriptor + val me = meD.resultingDescriptor.originalIfTypeRefinementEnabled + val other = otherD.resultingDescriptor.originalIfTypeRefinementEnabled val ignoreReturnType = isFromSources(me) != isFromSources(other) if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent( me, @@ -143,6 +143,8 @@ open class OverloadingConflictResolver( return result } + private val CallableDescriptor.originalIfTypeRefinementEnabled get() = if (isTypeRefinementEnabled) original else this + private fun Collection.setIfOneOrEmpty() = when (size) { 0 -> emptySet() 1 -> setOf(single()) diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt new file mode 100644 index 00000000000..84b86d3228a --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface A { + fun foo(x: T) + fun foo(x: String) + + fun baz(x: E, y: String) + fun baz(x: String, y: E) +} + +fun baz(x: E, y: String) {} +fun baz(x: String, y: E) {} + +fun bar(x: A) { + x.foo("") + + x.baz("", "") + baz("", "") +} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.txt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.txt new file mode 100644 index 00000000000..9031f74f6d5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.txt @@ -0,0 +1,15 @@ +package + +public fun bar(/*0*/ x: A): kotlin.Unit +public fun baz(/*0*/ x: E, /*1*/ y: kotlin.String): kotlin.Unit +public fun baz(/*0*/ x: kotlin.String, /*1*/ y: E): kotlin.Unit + +public interface A { + public abstract fun baz(/*0*/ x: E, /*1*/ y: kotlin.String): kotlin.Unit + public abstract fun baz(/*0*/ x: kotlin.String, /*1*/ y: E): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ x: T): kotlin.Unit + public abstract fun foo(/*0*/ x: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index cfcb365010b..c131f6088ea 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -18100,6 +18100,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt"); } + @TestMetadata("genericClash.kt") + public void testGenericClash() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt"); + } + @TestMetadata("genericWithProjection.kt") public void testGenericWithProjection() throws Exception { runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericWithProjection.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 83ec993f7d0..458f5bdda73 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -18090,6 +18090,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/extensionReceiverAndVarargs.kt"); } + @TestMetadata("genericClash.kt") + public void testGenericClash() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericClash.kt"); + } + @TestMetadata("genericWithProjection.kt") public void testGenericWithProjection() throws Exception { runTest("compiler/testData/diagnostics/tests/resolve/overloadConflicts/genericWithProjection.kt"); diff --git a/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/common/common.kt b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/common/common.kt new file mode 100644 index 00000000000..d19352369f0 --- /dev/null +++ b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/common/common.kt @@ -0,0 +1,6 @@ +// KT-34027 +expect interface A { + fun foo(x: T) +} + +fun bar(): A = null!! diff --git a/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/dependencies.txt b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/dependencies.txt new file mode 100644 index 00000000000..157e0cfded1 --- /dev/null +++ b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/dependencies.txt @@ -0,0 +1,5 @@ +MODULE common { platform=[JVM, JS, Native] } + +MODULE js { platform=[JS] } + +js -> common { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/js/js.kt b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/js/js.kt new file mode 100644 index 00000000000..c05ad561753 --- /dev/null +++ b/idea/testData/multiplatform/correctOverloadResolutionAmbiguity/js/js.kt @@ -0,0 +1,8 @@ +actual interface A { + actual fun foo(x: T) + fun foo(x: String) +} + +fun main() { + bar().foo("") +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java index e4101e3904b..0a82e81d883 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java @@ -44,6 +44,11 @@ public class MultiplatformAnalysisTestGenerated extends AbstractMultiplatformAna runTest("idea/testData/multiplatform/constructorsOfExpect/"); } + @TestMetadata("correctOverloadResolutionAmbiguity") + public void testCorrectOverloadResolutionAmbiguity() throws Exception { + runTest("idea/testData/multiplatform/correctOverloadResolutionAmbiguity/"); + } + @TestMetadata("diamondModuleDependency1") public void testDiamondModuleDependency1() throws Exception { runTest("idea/testData/multiplatform/diamondModuleDependency1/");