[FIR] Implement SAM candidates discrimination
This commit is contained in:
@@ -110,7 +110,9 @@ class FirCallResolver(
|
|||||||
return resultFunctionCall
|
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 {
|
private fun collectCandidates(functionCall: FirFunctionCall): ResolutionResult {
|
||||||
val explicitReceiver = functionCall.explicitReceiver
|
val explicitReceiver = functionCall.explicitReceiver
|
||||||
@@ -289,7 +291,7 @@ class FirCallResolver(
|
|||||||
symbol: FirClassSymbol<*>,
|
symbol: FirClassSymbol<*>,
|
||||||
typeArguments: List<FirTypeProjection>
|
typeArguments: List<FirTypeProjection>
|
||||||
): FirDelegatedConstructorCall? {
|
): FirDelegatedConstructorCall? {
|
||||||
val scope = symbol.fir.unsubstitutedScope(session, scopeSession) ?: return null
|
val scope = symbol.fir.unsubstitutedScope(session, scopeSession)
|
||||||
val className = symbol.classId.shortClassName
|
val className = symbol.classId.shortClassName
|
||||||
val callInfo = CallInfo(
|
val callInfo = CallInfo(
|
||||||
CallKind.Function,
|
CallKind.Function,
|
||||||
@@ -313,7 +315,9 @@ class FirCallResolver(
|
|||||||
return callResolver.selectCandidateFromGivenCandidates(delegatedConstructorCall, className, candidates)
|
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)
|
val result = CandidateCollector(this, resolutionStageRunner)
|
||||||
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
|
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
|
||||||
val bestCandidates = result.bestCandidates()
|
val bestCandidates = result.bestCandidates()
|
||||||
|
|||||||
@@ -306,7 +306,9 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
|||||||
|
|
||||||
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
// 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(
|
internal fun FirExpression.getExpectedType(
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class Candidate(
|
|||||||
lateinit var freshVariables: List<ConeTypeVariable>
|
lateinit var freshVariables: List<ConeTypeVariable>
|
||||||
var resultingTypeForCallableReference: ConeKotlinType? = null
|
var resultingTypeForCallableReference: ConeKotlinType? = null
|
||||||
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
|
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
|
||||||
|
var usesSAM: Boolean = false
|
||||||
|
|
||||||
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
|
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
|
||||||
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
|
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
|
||||||
|
|||||||
+18
@@ -28,6 +28,14 @@ class ConeOverloadConflictResolver(
|
|||||||
override fun chooseMaximallySpecificCandidates(
|
override fun chooseMaximallySpecificCandidates(
|
||||||
candidates: Set<Candidate>,
|
candidates: Set<Candidate>,
|
||||||
discriminateGenerics: Boolean
|
discriminateGenerics: Boolean
|
||||||
|
): Set<Candidate> {
|
||||||
|
return chooseMaximallySpecificCandidates(candidates, discriminateGenerics, discriminateSAMs = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chooseMaximallySpecificCandidates(
|
||||||
|
candidates: Set<Candidate>,
|
||||||
|
discriminateGenerics: Boolean,
|
||||||
|
discriminateSAMs: Boolean
|
||||||
): Set<Candidate> {
|
): Set<Candidate> {
|
||||||
findMaximallySpecificCall(candidates, false)?.let { return setOf(it) }
|
findMaximallySpecificCall(candidates, false)?.let { return setOf(it) }
|
||||||
|
|
||||||
@@ -35,6 +43,16 @@ class ConeOverloadConflictResolver(
|
|||||||
findMaximallySpecificCall(candidates, true)?.let { return setOf(it) }
|
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
|
return candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
fun test(list: MutableList<String>) {
|
fun test(list: MutableList<String>) {
|
||||||
list.<!AMBIGUITY!>removeAll<!> {
|
list.removeAll {
|
||||||
<!UNRESOLVED_REFERENCE!>it<!>.<!AMBIGUITY!>isEmpty<!>()
|
it.isEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
FILE: inapplicableRemoveAll.kt
|
FILE: inapplicableRemoveAll.kt
|
||||||
public final fun test(list: R|kotlin/collections/MutableList<kotlin/String>|): R|kotlin/Unit| {
|
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]| {
|
R|<local>/list|.R|kotlin/collections/removeAll|<R|kotlin/String|>(<L> = removeAll@fun <anonymous>(it: R|kotlin/String|): R|kotlin/Boolean| {
|
||||||
<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>/it|.R|kotlin/text/isEmpty|()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -11,8 +11,8 @@ public interface Runnable {
|
|||||||
// FILE: k.kt
|
// FILE: k.kt
|
||||||
|
|
||||||
fun fail() {
|
fun fail() {
|
||||||
<!AMBIGUITY!>foo<!>({ }, { })
|
foo({ }, { })
|
||||||
<!AMBIGUITY!>foo<!>(::bar, { })
|
foo(::bar, { })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(f: Runnable, selector: () -> Unit) {}
|
fun foo(f: Runnable, selector: () -> Unit) {}
|
||||||
|
|||||||
+1
-1
@@ -7,4 +7,4 @@ object X2
|
|||||||
fun <T1> foo(x: T1, f: (T1) -> T1) = X1
|
fun <T1> foo(x: T1, f: (T1) -> T1) = X1
|
||||||
fun <T2> foo(xf: () -> T2, f: (T2) -> T2) = X2
|
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
|
interface C : B, Other
|
||||||
|
|
||||||
fun test(c: C) {
|
fun test(c: C) {
|
||||||
c.<!AMBIGUITY!>pluginManagement<!> {
|
c.pluginManagement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user