From 3f95ac341c97dc75e10a3236f3f15141da906701 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 28 Jan 2020 18:26:30 +0300 Subject: [PATCH] [FIR] Implement SAM candidates discrimination --- .../jetbrains/kotlin/fir/FirCallResolver.kt | 10 +++++++--- .../kotlin/fir/resolve/calls/Arguments.kt | 4 +++- .../kotlin/fir/resolve/calls/Candidate.kt | 1 + .../calls/ConeOverloadConflictResolver.kt | 18 ++++++++++++++++++ .../stdlib/problems/inapplicableRemoveAll.kt | 4 ++-- .../stdlib/problems/inapplicableRemoveAll.txt | 4 ++-- .../platformTypes/methodCall/kt27565.fir.kt | 4 ++-- .../overloadConflicts/allLambdas.fir.kt | 2 +- ...andidatesFromKotlinAndJavaInOneScope.fir.kt | 2 +- 9 files changed, 37 insertions(+), 12 deletions(-) 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 d2db9911b46..ac130f71ecf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -110,7 +110,9 @@ class FirCallResolver( return resultFunctionCall } - private data class ResolutionResult(val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection) + private data class ResolutionResult( + val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection + ) private fun collectCandidates(functionCall: FirFunctionCall): ResolutionResult { val explicitReceiver = functionCall.explicitReceiver @@ -289,7 +291,7 @@ class FirCallResolver( symbol: FirClassSymbol<*>, typeArguments: List ): FirDelegatedConstructorCall? { - val scope = symbol.fir.unsubstitutedScope(session, scopeSession) ?: return null + val scope = symbol.fir.unsubstitutedScope(session, scopeSession) val className = symbol.classId.shortClassName val callInfo = CallInfo( CallKind.Function, @@ -313,7 +315,9 @@ class FirCallResolver( return callResolver.selectCandidateFromGivenCandidates(delegatedConstructorCall, className, candidates) } - fun selectCandidateFromGivenCandidates(call: T, name: Name, candidates: Collection): T where T : FirResolvable, T : FirCall { + private fun selectCandidateFromGivenCandidates( + call: T, name: Name, candidates: Collection + ): T where T : FirResolvable, T : FirCall { val result = CandidateCollector(this, resolutionStageRunner) candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) } val bestCandidates = result.bestCandidates() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 83bb7644403..1f7b246ea36 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -306,7 +306,9 @@ private fun Candidate.getExpectedTypeWithSAMConversion( // TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!)) - return samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType) ?: return null + return samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType).apply { + usesSAM = true + } ?: return null } internal fun FirExpression.getExpectedType( 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 e8cd8dabcae..40590695b37 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 @@ -104,6 +104,7 @@ class Candidate( lateinit var freshVariables: List var resultingTypeForCallableReference: ConeKotlinType? = null var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null + var usesSAM: Boolean = false var argumentMapping: Map? = null val postponedAtoms = mutableListOf() 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 8d383996e60..c503aa9b8f2 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 @@ -28,6 +28,14 @@ class ConeOverloadConflictResolver( override fun chooseMaximallySpecificCandidates( candidates: Set, discriminateGenerics: Boolean + ): Set { + return chooseMaximallySpecificCandidates(candidates, discriminateGenerics, discriminateSAMs = true) + } + + private fun chooseMaximallySpecificCandidates( + candidates: Set, + discriminateGenerics: Boolean, + discriminateSAMs: Boolean ): Set { findMaximallySpecificCall(candidates, false)?.let { return setOf(it) } @@ -35,6 +43,16 @@ class ConeOverloadConflictResolver( findMaximallySpecificCall(candidates, true)?.let { return setOf(it) } } + if (discriminateSAMs) { + val filtered = candidates.filterTo(mutableSetOf()) { !it.usesSAM } + when (filtered.size) { + 1 -> return filtered + 0, candidates.size -> { + } + else -> return chooseMaximallySpecificCandidates(filtered, discriminateGenerics, discriminateSAMs = false) + } + } + return candidates } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.kt b/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.kt index 9ba5ff3516f..ca551804642 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.kt +++ b/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.kt @@ -1,5 +1,5 @@ fun test(list: MutableList) { - list.removeAll { - it.isEmpty() + list.removeAll { + it.isEmpty() } } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.txt b/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.txt index 118b833ff7d..d1dd7f6154b 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/problems/inapplicableRemoveAll.txt @@ -1,7 +1,7 @@ FILE: inapplicableRemoveAll.kt public final fun test(list: R|kotlin/collections/MutableList|): R|kotlin/Unit| { - R|/list|.#( = removeAll@fun (): R|ERROR CLASS: Ambiguity: isEmpty, [kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/text/isEmpty]| { - #.#() + R|/list|.R|kotlin/collections/removeAll|( = removeAll@fun (it: R|kotlin/String|): R|kotlin/Boolean| { + R|/it|.R|kotlin/text/isEmpty|() } ) } diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/kt27565.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/kt27565.fir.kt index 8edd7891956..fb32dda83fc 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/methodCall/kt27565.fir.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/kt27565.fir.kt @@ -11,8 +11,8 @@ public interface Runnable { // FILE: k.kt fun fail() { - foo({ }, { }) - foo(::bar, { }) + foo({ }, { }) + foo(::bar, { }) } fun foo(f: Runnable, selector: () -> Unit) {} diff --git a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/allLambdas.fir.kt b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/allLambdas.fir.kt index b85b6f1d582..fbfedb7bc2a 100644 --- a/compiler/testData/diagnostics/tests/resolve/overloadConflicts/allLambdas.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/overloadConflicts/allLambdas.fir.kt @@ -7,4 +7,4 @@ object X2 fun foo(x: T1, f: (T1) -> T1) = X1 fun foo(xf: () -> T2, f: (T2) -> T2) = X2 -val test: X2 = foo({ 0 }, { it -> it + 1 }) \ No newline at end of file +val test: X2 = foo({ 0 }, { it -> it + 1 }) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/samConversions/sameCandidatesFromKotlinAndJavaInOneScope.fir.kt b/compiler/testData/diagnostics/tests/samConversions/sameCandidatesFromKotlinAndJavaInOneScope.fir.kt index 367a6f5ad58..8f59ee27653 100644 --- a/compiler/testData/diagnostics/tests/samConversions/sameCandidatesFromKotlinAndJavaInOneScope.fir.kt +++ b/compiler/testData/diagnostics/tests/samConversions/sameCandidatesFromKotlinAndJavaInOneScope.fir.kt @@ -21,6 +21,6 @@ interface B { interface C : B, Other fun test(c: C) { - c.pluginManagement { + c.pluginManagement { } } \ No newline at end of file