FIR: discriminate candidates with suspend conversion
This commit is contained in:
committed by
Mikhail Glukhikh
parent
6de8ba40c1
commit
5fdd06676f
@@ -240,7 +240,6 @@ fun Candidate.resolvePlainArgumentType(
|
||||
|
||||
// If the argument is of functional type and the expected type is a suspend function type, we need to do "suspend conversion."
|
||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||
// TODO: should prefer another candidate without suspend conversion when ambiguous
|
||||
if (expectedType?.isSuspendFunctionType(session) == true &&
|
||||
argumentTypeForApplicabilityCheck.isBuiltinFunctionalType(session) &&
|
||||
!argumentTypeForApplicabilityCheck.isSuspendFunctionType(session)
|
||||
@@ -253,6 +252,7 @@ fun Candidate.resolvePlainArgumentType(
|
||||
isKFunctionType = argumentTypeForApplicabilityCheck.isKFunctionType(session)
|
||||
)
|
||||
substitutor.substituteOrSelf(argumentTypeForApplicabilityCheck)
|
||||
usesSuspendConversion = true
|
||||
}
|
||||
|
||||
checkApplicabilityForArgumentType(
|
||||
|
||||
@@ -97,6 +97,7 @@ class Candidate(
|
||||
var resultingTypeForCallableReference: ConeKotlinType? = null
|
||||
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
|
||||
var usesSAM: Boolean = false
|
||||
var usesSuspendConversion: Boolean = false
|
||||
|
||||
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
|
||||
lateinit var typeArgumentMapping: TypeArgumentMapping
|
||||
|
||||
+25
-4
@@ -42,7 +42,7 @@ class ConeOverloadConflictResolver(
|
||||
candidates
|
||||
|
||||
return chooseMaximallySpecificCandidates(
|
||||
fixedCandidates, discriminateGenerics, discriminateAbstracts, discriminateSAMs = true
|
||||
fixedCandidates, discriminateGenerics, discriminateAbstracts, discriminateSAMs = true, discriminateSuspendConversions = true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ class ConeOverloadConflictResolver(
|
||||
candidates: Set<Candidate>,
|
||||
discriminateGenerics: Boolean,
|
||||
discriminateAbstracts: Boolean,
|
||||
discriminateSAMs: Boolean
|
||||
discriminateSAMs: Boolean,
|
||||
discriminateSuspendConversions: Boolean,
|
||||
): Set<Candidate> {
|
||||
findMaximallySpecificCall(candidates, false)?.let { return setOf(it) }
|
||||
|
||||
@@ -78,7 +79,23 @@ class ConeOverloadConflictResolver(
|
||||
0, candidates.size -> {
|
||||
}
|
||||
else -> return chooseMaximallySpecificCandidates(
|
||||
filtered, discriminateGenerics, discriminateAbstracts, discriminateSAMs = false
|
||||
filtered, discriminateGenerics, discriminateAbstracts, discriminateSAMs = false, discriminateSuspendConversions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (discriminateSuspendConversions) {
|
||||
val filtered = candidates.filterTo(mutableSetOf()) { !it.usesSuspendConversion }
|
||||
when (filtered.size) {
|
||||
1 -> return filtered
|
||||
0, candidates.size -> {
|
||||
}
|
||||
else -> return chooseMaximallySpecificCandidates(
|
||||
filtered,
|
||||
discriminateGenerics,
|
||||
discriminateAbstracts,
|
||||
discriminateSAMs = false,
|
||||
discriminateSuspendConversions = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -90,7 +107,11 @@ class ConeOverloadConflictResolver(
|
||||
0, candidates.size -> {
|
||||
}
|
||||
else -> return chooseMaximallySpecificCandidates(
|
||||
filtered, discriminateGenerics, discriminateAbstracts = false, discriminateSAMs = false
|
||||
filtered,
|
||||
discriminateGenerics,
|
||||
discriminateAbstracts = false,
|
||||
discriminateSAMs = false,
|
||||
discriminateSuspendConversions = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
||||
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
||||
else -> ConeKotlinErrorType(ConeSimpleDiagnostic("Unknown callable kind: ${fir::class}", DiagnosticKind.UnknownCallableKind))
|
||||
}.let(candidate.substitutor::substituteOrSelf)
|
||||
|
||||
candidate.usesSuspendConversion = requireSuspendConversion
|
||||
candidate.resultingTypeForCallableReference = resultingType
|
||||
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
|
||||
addOtherSystem(candidate.system.asReadOnlyStorage())
|
||||
|
||||
Vendored
+1
-1
@@ -14,6 +14,6 @@ fun test1() {
|
||||
|
||||
// candidate without suspend conversions is more specific
|
||||
fun test2(f: () -> Int, g: suspend () -> Int) {
|
||||
<!AMBIGUITY!>foo<!>(f)
|
||||
foo(f)
|
||||
foo(g)
|
||||
}
|
||||
+1
-1
@@ -15,5 +15,5 @@ fun test4(): suspend () -> Unit = useSuspendFn {}
|
||||
fun test5() = useSuspendFn {}
|
||||
|
||||
fun test5(sfn: suspend () -> Unit) = ambiguous(sfn)
|
||||
fun test6(fn: () -> Unit) = <!AMBIGUITY!>ambiguous<!>(fn)
|
||||
fun test6(fn: () -> Unit) = ambiguous(fn)
|
||||
fun test7(): () -> Unit = <!AMBIGUITY!>ambiguous<!> {}
|
||||
Reference in New Issue
Block a user