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
This commit is contained in:
Mikhail Glukhikh
2023-12-18 16:45:39 +01:00
committed by Space Team
parent a7dc381b93
commit 087edc026d
13 changed files with 70 additions and 9 deletions
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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() {
@@ -163,6 +163,11 @@ class ConeOverloadConflictResolver(
discriminateSuspendConversions: Boolean,
discriminateByUnwrappedSmartCastOrigin: Boolean,
): Set<Candidate> {
val withoutLowPrioritySAM = candidates.filterTo(mutableSetOf()) { !it.shouldHaveLowPriorityDueToSAM(transformerComponents) }
if (withoutLowPrioritySAM.size == 1) {
return withoutLowPrioritySAM
}
findMaximallySpecificCall(candidates, false)?.let { return setOf(it) }
if (discriminateGenerics) {
@@ -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
@@ -41,7 +41,7 @@ object Test3 {
fun test(f: () -> Unit) {
val result = foo(1, f)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>result<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
}
}
@@ -53,7 +53,7 @@ object Test4 {
fun test() {
val result = foo(1, ::bar)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>result<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
}
}
@@ -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
}
@@ -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.<!UNRESOLVED_REFERENCE!>length<!>
val x = bar() { foo() } // OK with default current 1.5/1.6, Error with DisableCompatibilityModeForNewInference enabled, Ok in K2
x.length
}
@@ -1,6 +1,5 @@
// !LANGUAGE: +DisableCompatibilityModeForNewInference
// SKIP_TXT
// FIR_IDENTICAL
// FULL_JDK
fun <T> 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.<!UNRESOLVED_REFERENCE!>length<!>
}
@@ -0,0 +1,14 @@
// FIR_IDENTICAL
// !LANGUAGE: -DisableCompatibilityModeForNewInference
// SKIP_TXT
// FULL_JDK
fun <T> 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
}
@@ -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 {