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 52b68678bad..7f4c37e509c 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 @@ -21926,6 +21926,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/j+k/recursiveSelfTypes.kt"); } + @Test + @TestMetadata("runnableOrCallable.kt") + public void testRunnableOrCallable() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt"); + } + @Test @TestMetadata("safeCallDefinitelyNotNull.kt") public void testSafeCallDefinitelyNotNull() 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 594b55f84a8..27c46aa40fd 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 @@ -21926,6 +21926,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/j+k/recursiveSelfTypes.kt"); } + @Test + @TestMetadata("runnableOrCallable.kt") + public void testRunnableOrCallable() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt"); + } + @Test @TestMetadata("safeCallDefinitelyNotNull.kt") public void testSafeCallDefinitelyNotNull() 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 bb54b201722..8befaff6917 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 @@ -21920,6 +21920,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/j+k/recursiveSelfTypes.kt"); } + @Test + @TestMetadata("runnableOrCallable.kt") + public void testRunnableOrCallable() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt"); + } + @Test @TestMetadata("safeCallDefinitelyNotNull.kt") public void testSafeCallDefinitelyNotNull() 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 d7ae2eb1d2e..c37c3cd9169 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 @@ -21926,6 +21926,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/j+k/recursiveSelfTypes.kt"); } + @Test + @TestMetadata("runnableOrCallable.kt") + public void testRunnableOrCallable() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt"); + } + @Test @TestMetadata("safeCallDefinitelyNotNull.kt") public void testSafeCallDefinitelyNotNull() throws Exception { 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 878bff8b6a3..abb28198b74 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.calls +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration @@ -13,9 +14,11 @@ import org.jetbrains.kotlin.fir.declarations.utils.isActual import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents +import org.jetbrains.kotlin.fir.resolve.inference.ResolvedCallableReferenceAtom import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.impl.overrides @@ -79,10 +82,15 @@ class ConeOverloadConflictResolver( candidates // The same logic as at - val noOverrides = filterOverrides(fixedCandidates) - + val candidatesWithoutOverrides = filterOverrides(fixedCandidates) + val noCompatibilityMode = inferenceComponents.session.languageVersionSettings.supportsFeature( + LanguageFeature.DisableCompatibilityModeForNewInference + ) return chooseMaximallySpecificCandidates( - noOverrides, + candidatesWithoutOverrides, + // (in compatibility mode the next two are already filtered on tower resolver level) + discriminateLowPrioritySAMs = noCompatibilityMode, + discriminateAdaptationsInPostponedAtoms = noCompatibilityMode, discriminateGenerics, discriminateAbstracts, discriminateSAMs = true, @@ -156,6 +164,8 @@ class ConeOverloadConflictResolver( private fun chooseMaximallySpecificCandidates( candidates: Set, + discriminateLowPrioritySAMs: Boolean, + discriminateAdaptationsInPostponedAtoms: Boolean, discriminateGenerics: Boolean, discriminateAbstracts: Boolean, // Only set to 'false' by recursive calls when the relevant discrimination kind has been already applied @@ -163,9 +173,42 @@ class ConeOverloadConflictResolver( discriminateSuspendConversions: Boolean, discriminateByUnwrappedSmartCastOrigin: Boolean, ): Set { - val withoutLowPrioritySAM = candidates.filterTo(mutableSetOf()) { !it.shouldHaveLowPriorityDueToSAM(transformerComponents) } - if (withoutLowPrioritySAM.size == 1) { - return withoutLowPrioritySAM + if (discriminateLowPrioritySAMs) { + val filtered = candidates.filterTo(mutableSetOf()) { !it.shouldHaveLowPriorityDueToSAM(transformerComponents) } + when (filtered.size) { + 1 -> return filtered + 0, candidates.size -> { + } + else -> return chooseMaximallySpecificCandidates( + filtered, + discriminateLowPrioritySAMs = false, + discriminateAdaptationsInPostponedAtoms, + discriminateGenerics, + discriminateAbstracts, + discriminateSAMs, + discriminateSuspendConversions, + discriminateByUnwrappedSmartCastOrigin, + ) + } + } + + if (discriminateAdaptationsInPostponedAtoms) { + val filtered = candidates.filterTo(mutableSetOf()) { !it.hasPostponedAtomWithAdaptation() } + when (filtered.size) { + 1 -> return filtered + 0, candidates.size -> { + } + else -> return chooseMaximallySpecificCandidates( + filtered, + discriminateLowPrioritySAMs, + discriminateAdaptationsInPostponedAtoms = false, + discriminateGenerics, + discriminateAbstracts, + discriminateSAMs, + discriminateSuspendConversions, + discriminateByUnwrappedSmartCastOrigin, + ) + } } findMaximallySpecificCall(candidates, false)?.let { return setOf(it) } @@ -181,7 +224,10 @@ class ConeOverloadConflictResolver( 0, candidates.size -> { } else -> return chooseMaximallySpecificCandidates( - filtered, discriminateGenerics, + filtered, + discriminateLowPrioritySAMs, + discriminateAdaptationsInPostponedAtoms, + discriminateGenerics, discriminateAbstracts, discriminateSAMs = false, discriminateSuspendConversions, @@ -198,6 +244,8 @@ class ConeOverloadConflictResolver( } else -> return chooseMaximallySpecificCandidates( filtered, + discriminateLowPrioritySAMs, + discriminateAdaptationsInPostponedAtoms, discriminateGenerics, discriminateAbstracts, discriminateSAMs, @@ -215,6 +263,8 @@ class ConeOverloadConflictResolver( } else -> return chooseMaximallySpecificCandidates( filtered, + discriminateLowPrioritySAMs, + discriminateAdaptationsInPostponedAtoms, discriminateGenerics, discriminateAbstracts = false, discriminateSAMs, @@ -259,6 +309,8 @@ class ConeOverloadConflictResolver( } else -> return chooseMaximallySpecificCandidates( filtered, + discriminateLowPrioritySAMs, + discriminateAdaptationsInPostponedAtoms, discriminateGenerics, discriminateAbstracts, discriminateSAMs, @@ -276,6 +328,13 @@ class ConeOverloadConflictResolver( return candidates } + private fun Candidate.hasPostponedAtomWithAdaptation(): Boolean { + return postponedAtoms.any { + it is ResolvedCallableReferenceAtom && + (it.resultingReference as? FirNamedReferenceWithCandidate)?.candidate?.callableReferenceAdaptation != null + } + } + private fun findMaximallySpecificCall( candidates: Set, discriminateGenerics: Boolean, diff --git a/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.fir.kt b/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.fir.kt new file mode 100644 index 00000000000..80b76b078fb --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.fir.kt @@ -0,0 +1,18 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER + +import kotlin.reflect.* + +interface A +interface B : A + +fun A.foo() {} + +fun take(f: (A) -> Unit) {} +fun take(f: () -> Unit) {} + +fun test() { + B::foo checkType { _>() } + + take(B::foo) +} diff --git a/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.kt b/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.kt index ef1fa5e6a85..806d960ee23 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.kt +++ b/compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_PARAMETER diff --git a/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt b/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt index 0138885a64c..de30df9b0cc 100644 --- a/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/unitAdaptationForReferenceCompatibility.fir.kt @@ -20,6 +20,6 @@ public interface Executor { fun f(): String = "test" class A { - fun schedule1(e: Executor): Future = e.submit(::f) + fun schedule1(e: Executor): Future = e.submit(::f) fun schedule2(e: Executor): Future = e.submit { f() } } diff --git a/compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt b/compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt new file mode 100644 index 00000000000..6a88cabd0d0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// FULL_JDK +// JVM_TARGET: 1.8 + +import java.util.concurrent.* + +abstract class Logger(val service: ScheduledExecutorService) { + lateinit var future: ScheduledFuture> + + abstract fun flush(): CompletableFuture + + fun init() { + future = service.schedule(this::flush, 0L, TimeUnit.MILLISECONDS) + } +} 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 f37f43eb908..689eee4ed9f 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 @@ -21926,6 +21926,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/j+k/recursiveSelfTypes.kt"); } + @Test + @TestMetadata("runnableOrCallable.kt") + public void testRunnableOrCallable() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/runnableOrCallable.kt"); + } + @Test @TestMetadata("safeCallDefinitelyNotNull.kt") public void testSafeCallDefinitelyNotNull() throws Exception {