From 6b7eeec181de0de5e2c3fbc36814da1a9ae10760 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Fri, 3 Nov 2023 12:06:01 +0100 Subject: [PATCH] [FIR] Fix candidate success check by checking if no diagnostic is unsuccessful Checking the current applicability isn't enough because in the presence of multiple diagnostics, the lowest applicability can be successful but a higher one isn't. #KT-63147 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ ...sticCompilerFE10TestDataTestGenerated.java | 6 ++++ ...eeOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 ++++ .../jetbrains/kotlin/fir/FirCallResolver.kt | 18 ++++++------ .../kotlin/fir/resolve/calls/Candidate.kt | 9 +++++- .../tests/resolve/dslMarker/lowPriority.kt | 28 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++ 8 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.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 1878bb12767..eb868d66849 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 @@ -28455,6 +28455,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt46969.kt"); } + @Test + @TestMetadata("lowPriority.kt") + public void testLowPriority() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt"); + } + @Test @TestMetadata("markedReceiverWithCapturedTypeArgument.kt") public void testMarkedReceiverWithCapturedTypeArgument() 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 acdf8ead553..26d5f381ea0 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 @@ -28455,6 +28455,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt46969.kt"); } + @Test + @TestMetadata("lowPriority.kt") + public void testLowPriority() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt"); + } + @Test @TestMetadata("markedReceiverWithCapturedTypeArgument.kt") public void testMarkedReceiverWithCapturedTypeArgument() 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 94f2e9b9460..f7886f2cee7 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 @@ -28443,6 +28443,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt46969.kt"); } + @Test + @TestMetadata("lowPriority.kt") + public void testLowPriority() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt"); + } + @Test @TestMetadata("markedReceiverWithCapturedTypeArgument.kt") public void testMarkedReceiverWithCapturedTypeArgument() 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 71204895ec6..8a54b886c33 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 @@ -28455,6 +28455,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt46969.kt"); } + @Test + @TestMetadata("lowPriority.kt") + public void testLowPriority() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt"); + } + @Test @TestMetadata("markedReceiverWithCapturedTypeArgument.kt") public void testMarkedReceiverWithCapturedTypeArgument() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 76e18dcec0b..010e24b9272 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -776,18 +776,18 @@ class FirCallResolver( candidates.size > 1 -> ConeAmbiguityError(name, applicability, candidates) - !applicability.isSuccess -> { + else -> { val candidate = candidates.single() - if (needTreatErrorCandidateAsResolved(candidate)) { - @OptIn(CodeFragmentAdjustment::class) - candidate.resetToResolved() - null - } else { - createConeDiagnosticForCandidateWithError(applicability, candidate) + runIf(!candidate.isSuccessful) { + if (needTreatErrorCandidateAsResolved(candidate)) { + @OptIn(CodeFragmentAdjustment::class) + candidate.resetToResolved() + null + } else { + createConeDiagnosticForCandidateWithError(applicability, candidate) + } } } - - else -> null } if (diagnostic != null) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index b39be1fa2ff..4cf6bbb4113 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -129,8 +129,15 @@ class Candidate( _diagnostics.clear() } + /** + * Note that [currentApplicability]`.isSuccessful == true` doesn't imply [isSuccessful]. + * + * This is because [currentApplicability] is equal to the lowest [ResolutionDiagnostic.applicability] of all [diagnostics], + * but in presence of more than one diagnostic, the lowest one can be successful while a higher one isn't, e.g., the combination + * of [CandidateApplicability.RESOLVED_NEED_PRESERVE_COMPATIBILITY] and [CandidateApplicability.RESOLVED_WITH_ERROR]. + */ val isSuccessful: Boolean - get() = currentApplicability.isSuccess && (!systemInitialized || !system.hasContradiction) + get() = diagnostics.all { it.applicability.isSuccess } && (!systemInitialized || !system.hasContradiction) var passedStages: Int = 0 diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt new file mode 100644 index 00000000000..93cd54a2b79 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt @@ -0,0 +1,28 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER, -ERROR_SUPPRESSION +@DslMarker +annotation class Ann + +@Ann +class A { + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + @kotlin.internal.LowPriorityInOverloadResolution + fun a() = 1 +} + +@Ann +class B { + fun b() = 2 +} + +fun foo(x: A.() -> Unit) {} +fun bar(x: B.() -> Unit) {} + +fun test() { + foo { + a() + bar { + a() + } + } +} 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 7713cd85c56..e35f43348d9 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 @@ -30443,6 +30443,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/kt46969.kt"); } + @Test + @TestMetadata("lowPriority.kt") + public void testLowPriority() throws Exception { + runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/lowPriority.kt"); + } + @Test @TestMetadata("markedReceiverWithCapturedTypeArgument.kt") public void testMarkedReceiverWithCapturedTypeArgument() throws Exception {