From 087edc026db13a0da13a33133a1d621f6277dd2d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 18 Dec 2023 16:45:39 +0100 Subject: [PATCH] K2: discriminate particular SAMs in the first place in ConeOverloadConflictResolver Before this commit, we discriminated particular candidates with SAM during resolution stages. More precisely, candidates from Kotlin which used Java SAM types, were discriminated allowing go up the tower for better candidates. After disabling compatibility mode for new inference, it's not so, but now we discriminate similar candidates in ConeOverloadConflictResolver. This does not allow going up the tower, but allows to select better candidate at similar tower level. Related to KT-63558, KT-64306 --- ...osticCompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...iagnosticCompilerFE10TestDataTestGenerated.java | 6 ++++++ ...ghtTreeOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../FirPsiOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../calls/AbstractConeCallConflictResolver.kt | 2 +- .../resolve/calls/ConeOverloadConflictResolver.kt | 5 +++++ .../kotlin/fir/resolve/calls/ResolutionStages.kt | 13 ++++++++++++- ...ityResolveToOuterScopeForKotlinFunctions.fir.kt | 4 ++-- .../tests/samConversions/samPriorityVsGeneric.kt | 3 ++- ...mPriorityVsGenericCompatibilityDisabled.fir.kt} | 5 +++-- .../samPriorityVsGenericCompatibilityDisabled.kt | 3 +-- .../samPriorityVsGenericCompatibilityEnabled.kt | 14 ++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 13 files changed, 70 insertions(+), 9 deletions(-) rename compiler/testData/diagnostics/tests/samConversions/{samPriorityVsGeneric.fir.kt => samPriorityVsGenericCompatibilityDisabled.fir.kt} (60%) create mode 100644 compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index f5ed15ce852..52b68678bad 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -32476,6 +32476,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt"); } + @Test + @TestMetadata("samPriorityVsGenericCompatibilityEnabled.kt") + public void testSamPriorityVsGenericCompatibilityEnabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt"); + } + @Test @TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt") public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 5b49e315a0e..594b55f84a8 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -32476,6 +32476,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt"); } + @Test + @TestMetadata("samPriorityVsGenericCompatibilityEnabled.kt") + public void testSamPriorityVsGenericCompatibilityEnabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt"); + } + @Test @TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt") public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index ef58bc7a351..bb54b201722 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -30310,6 +30310,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt"); } + @Test + @TestMetadata("samPriorityVsGenericCompatibilityEnabled.kt") + public void testSamPriorityVsGenericCompatibilityEnabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt"); + } + @Test @TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt") public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 7a504e49a7f..d7ae2eb1d2e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -30322,6 +30322,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt"); } + @Test + @TestMetadata("samPriorityVsGenericCompatibilityEnabled.kt") + public void testSamPriorityVsGenericCompatibilityEnabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt"); + } + @Test @TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt") public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/AbstractConeCallConflictResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/AbstractConeCallConflictResolver.kt index 23bd9e5f647..5a519530a51 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/AbstractConeCallConflictResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/AbstractConeCallConflictResolver.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment abstract class AbstractConeCallConflictResolver( private val specificityComparator: TypeSpecificityComparator, protected val inferenceComponents: InferenceComponents, - private val transformerComponents: BodyResolveComponents, + protected val transformerComponents: BodyResolveComponents, private val considerMissingArgumentsInSignatures: Boolean, ) : ConeCallConflictResolver() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt index 7f11a7752dc..878bff8b6a3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt @@ -163,6 +163,11 @@ class ConeOverloadConflictResolver( discriminateSuspendConversions: Boolean, discriminateByUnwrappedSmartCastOrigin: Boolean, ): Set { + val withoutLowPrioritySAM = candidates.filterTo(mutableSetOf()) { !it.shouldHaveLowPriorityDueToSAM(transformerComponents) } + if (withoutLowPrioritySAM.size == 1) { + return withoutLowPrioritySAM + } + findMaximallySpecificCall(candidates, false)?.let { return setOf(it) } if (discriminateGenerics) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 135d99bf6ba..14034b35076 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.matchingParameterFunctionType import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.references.FirThisReference +import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.directExpansionType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.* @@ -512,7 +513,7 @@ internal object CheckArguments : CheckerStage() { } // Logic description: only candidates from Kotlin, but using Java SAM types, are discriminated - candidate.usesSAM && !candidate.isJavaApplicableCandidate() -> { + candidate.shouldHaveLowPriorityDueToSAM(context.bodyResolveComponents) -> { if (argumentMapping.values.any { val coneType = it.returnTypeRef.coneType context.bodyResolveComponents.samResolver.isSamType(coneType) && @@ -527,6 +528,16 @@ internal object CheckArguments : CheckerStage() { } } +internal fun Candidate.shouldHaveLowPriorityDueToSAM(bodyResolveComponents: BodyResolveComponents): Boolean { + if (!usesSAM || isJavaApplicableCandidate()) return false + return argumentMapping!!.values.any { + val coneType = it.returnTypeRef.coneType + bodyResolveComponents.samResolver.isSamType(coneType) && + // Candidate is not from Java, so no flexible types are possible here + coneType.toRegularClassSymbol(bodyResolveComponents.session)?.isJavaOrEnhancement == true + } +} + private fun Candidate.isJavaApplicableCandidate(): Boolean { val symbol = symbol as? FirFunctionSymbol ?: return false if (symbol.isJavaOrEnhancement) return true diff --git a/compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.fir.kt b/compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.fir.kt index 11415254d19..eb1fa1074ed 100644 --- a/compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.fir.kt @@ -41,7 +41,7 @@ object Test3 { fun test(f: () -> Unit) { val result = foo(1, f) - result + result } } @@ -53,7 +53,7 @@ object Test4 { fun test() { val result = foo(1, ::bar) - result + result } } diff --git a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.kt b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.kt index 5acf822f49d..5bd51db6cc4 100644 --- a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.kt +++ b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // SKIP_TXT // FULL_JDK @@ -7,6 +8,6 @@ fun bar(action: java.lang.Runnable) { } fun foo(): String = "" fun main() { - val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled + val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled, Ok in K2 x.length } diff --git a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.fir.kt b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.fir.kt similarity index 60% rename from compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.fir.kt rename to compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.fir.kt index 67300b10c94..33223b6b586 100644 --- a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGeneric.fir.kt +++ b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.fir.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: +DisableCompatibilityModeForNewInference // SKIP_TXT // FULL_JDK @@ -7,6 +8,6 @@ fun bar(action: java.lang.Runnable) { } fun foo(): String = "" fun main() { - val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled - x.length + val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled, Ok in K2 + x.length } diff --git a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt index 80b75729482..a5792e2e1e3 100644 --- a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt +++ b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +DisableCompatibilityModeForNewInference // SKIP_TXT -// FIR_IDENTICAL // FULL_JDK fun bar(action: () -> T): T = action() @@ -9,6 +8,6 @@ fun bar(action: java.lang.Runnable) { } fun foo(): String = "" fun main() { - val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled + val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled, Ok in K2 x.length } diff --git a/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt new file mode 100644 index 00000000000..38261e337d8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt @@ -0,0 +1,14 @@ +// FIR_IDENTICAL +// !LANGUAGE: -DisableCompatibilityModeForNewInference +// SKIP_TXT +// FULL_JDK + +fun bar(action: () -> T): T = action() +fun bar(action: java.lang.Runnable) { } + +fun foo(): String = "" + +fun main() { + val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled, Ok in K2 + x.length +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index fd66c4ab443..f37f43eb908 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -32476,6 +32476,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityDisabled.kt"); } + @Test + @TestMetadata("samPriorityVsGenericCompatibilityEnabled.kt") + public void testSamPriorityVsGenericCompatibilityEnabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/samConversions/samPriorityVsGenericCompatibilityEnabled.kt"); + } + @Test @TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt") public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception {