[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
This commit is contained in:
Kirill Rakhman
2023-11-03 12:06:01 +01:00
committed by Space Team
parent 0d36462c58
commit 6b7eeec181
8 changed files with 75 additions and 10 deletions
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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) {
@@ -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
@@ -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 {
<!DSL_SCOPE_VIOLATION!>a<!>()
}
}
}
@@ -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 {