[FIR] Implement SAM candidates discrimination
This commit is contained in:
@@ -110,7 +110,9 @@ class FirCallResolver(
|
||||
return resultFunctionCall
|
||||
}
|
||||
|
||||
private data class ResolutionResult(val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>)
|
||||
private data class ResolutionResult(
|
||||
val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>
|
||||
)
|
||||
|
||||
private fun collectCandidates(functionCall: FirFunctionCall): ResolutionResult {
|
||||
val explicitReceiver = functionCall.explicitReceiver
|
||||
@@ -289,7 +291,7 @@ class FirCallResolver(
|
||||
symbol: FirClassSymbol<*>,
|
||||
typeArguments: List<FirTypeProjection>
|
||||
): 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 <T> selectCandidateFromGivenCandidates(call: T, name: Name, candidates: Collection<Candidate>): T where T : FirResolvable, T : FirCall {
|
||||
private fun <T> selectCandidateFromGivenCandidates(
|
||||
call: T, name: Name, candidates: Collection<Candidate>
|
||||
): T where T : FirResolvable, T : FirCall {
|
||||
val result = CandidateCollector(this, resolutionStageRunner)
|
||||
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
|
||||
val bestCandidates = result.bestCandidates()
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -104,6 +104,7 @@ class Candidate(
|
||||
lateinit var freshVariables: List<ConeTypeVariable>
|
||||
var resultingTypeForCallableReference: ConeKotlinType? = null
|
||||
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
|
||||
var usesSAM: Boolean = false
|
||||
|
||||
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
|
||||
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
|
||||
|
||||
+18
@@ -28,6 +28,14 @@ class ConeOverloadConflictResolver(
|
||||
override fun chooseMaximallySpecificCandidates(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean
|
||||
): Set<Candidate> {
|
||||
return chooseMaximallySpecificCandidates(candidates, discriminateGenerics, discriminateSAMs = true)
|
||||
}
|
||||
|
||||
private fun chooseMaximallySpecificCandidates(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean,
|
||||
discriminateSAMs: Boolean
|
||||
): Set<Candidate> {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
fun test(list: MutableList<String>) {
|
||||
list.<!AMBIGUITY!>removeAll<!> {
|
||||
<!UNRESOLVED_REFERENCE!>it<!>.<!AMBIGUITY!>isEmpty<!>()
|
||||
list.removeAll {
|
||||
it.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
FILE: inapplicableRemoveAll.kt
|
||||
public final fun test(list: R|kotlin/collections/MutableList<kotlin/String>|): R|kotlin/Unit| {
|
||||
R|<local>/list|.<Ambiguity: removeAll, [kotlin/collections/removeAll, kotlin/collections/removeAll, kotlin/collections/removeAll, kotlin/collections/removeAll]>#(<L> = removeAll@fun <anonymous>(): 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]| {
|
||||
<Unresolved name: it>#.<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|<local>/list|.R|kotlin/collections/removeAll|<R|kotlin/String|>(<L> = removeAll@fun <anonymous>(it: R|kotlin/String|): R|kotlin/Boolean| {
|
||||
R|<local>/it|.R|kotlin/text/isEmpty|()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ public interface Runnable {
|
||||
// FILE: k.kt
|
||||
|
||||
fun fail() {
|
||||
<!AMBIGUITY!>foo<!>({ }, { })
|
||||
<!AMBIGUITY!>foo<!>(::bar, { })
|
||||
foo({ }, { })
|
||||
foo(::bar, { })
|
||||
}
|
||||
|
||||
fun foo(f: Runnable, selector: () -> Unit) {}
|
||||
|
||||
+1
-1
@@ -7,4 +7,4 @@ object X2
|
||||
fun <T1> foo(x: T1, f: (T1) -> T1) = X1
|
||||
fun <T2> foo(xf: () -> T2, f: (T2) -> T2) = X2
|
||||
|
||||
val test: X2 = <!AMBIGUITY!>foo<!>({ 0 }, { it -> it + 1 })
|
||||
val test: X2 = foo({ 0 }, { it -> it + 1 })
|
||||
Vendored
+1
-1
@@ -21,6 +21,6 @@ interface B {
|
||||
interface C : B, Other
|
||||
|
||||
fun test(c: C) {
|
||||
c.<!AMBIGUITY!>pluginManagement<!> {
|
||||
c.pluginManagement {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user