[FIR] Handle default parameters when checking callable reference type

#KT-36759 Fixed
This commit is contained in:
Mikhail Glukhikh
2020-02-19 10:59:43 +03:00
parent 04e6c63cc9
commit 9017654b9d
10 changed files with 29 additions and 18 deletions
@@ -230,7 +230,10 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
val resultingType: ConeKotlinType = when (fir) {
is FirFunction -> createKFunctionType(fir, resultingReceiverType, returnTypeRef)
is FirFunction -> createKFunctionType(
fir, resultingReceiverType, returnTypeRef,
expectedParameterNumberWithReceiver = expectedType?.let { it.typeArguments.size - 1 }
)
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}")
}.let(candidate.substitutor::substituteOrSelf)
@@ -284,10 +287,20 @@ private fun createKPropertyType(
private fun createKFunctionType(
function: FirFunction<*>,
receiverType: ConeKotlinType?,
returnTypeRef: FirResolvedTypeRef
returnTypeRef: FirResolvedTypeRef,
expectedParameterNumberWithReceiver: Int?
): ConeKotlinType {
val parameterTypes = function.valueParameters.map {
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for parameter $it")
val parameterTypes = mutableListOf<ConeKotlinType>()
val expectedParameterNumber = when {
expectedParameterNumberWithReceiver == null -> null
receiverType != null -> expectedParameterNumberWithReceiver - 1
else -> expectedParameterNumberWithReceiver
}
for ((index, valueParameter) in function.valueParameters.withIndex()) {
if (expectedParameterNumber == null || index < expectedParameterNumber || valueParameter.defaultValue == null) {
parameterTypes += valueParameter.returnTypeRef.coneTypeSafe()
?: ConeKotlinErrorType("No type for parameter $valueParameter")
}
}
return createFunctionalType(
@@ -5,5 +5,5 @@ class A {
inline fun <T> T.myLet(block: (T) -> Unit) {}
fun test(a: A, s: String) {
s.<!INAPPLICABLE_CANDIDATE!>myLet<!>(a::foo)
s.myLet(a::foo)
}
@@ -11,5 +11,5 @@ FILE: callableReferencesAndDefaultParameters.kt
public final inline fun <T> R|T|.myLet(block: R|(T) -> kotlin/Unit|): R|kotlin/Unit| {
}
public final fun test(a: R|A|, s: R|kotlin/String|): R|kotlin/Unit| {
R|<local>/s|.<Inapplicable(INAPPLICABLE): [/myLet]>#(R|<local>/a|::R|/A.foo|)
R|<local>/s|.R|/myLet|<R|kotlin/String|>(R|<local>/a|::R|/A.foo|)
}