FIR: Support callable references to declarations with implicit types
^KT-32725 In Progress
This commit is contained in:
@@ -176,16 +176,22 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
|||||||
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||||
val outerCsBuilder = callInfo.outerCSBuilder ?: return
|
val outerCsBuilder = callInfo.outerCSBuilder ?: return
|
||||||
val expectedType = callInfo.expectedType ?: return
|
val expectedType = callInfo.expectedType ?: return
|
||||||
|
val candidateSymbol = candidate.symbol as? FirCallableSymbol<*> ?: return
|
||||||
|
|
||||||
val resultingReceiverType = when (callInfo.lhs) {
|
val resultingReceiverType = when (callInfo.lhs) {
|
||||||
is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier }
|
is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier }
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
val fir = candidate.symbol.fir
|
val fir = with(candidate.bodyResolveComponents) {
|
||||||
|
candidateSymbol.phasedFir
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
||||||
|
|
||||||
val resultingType: ConeKotlinType = when (fir) {
|
val resultingType: ConeKotlinType = when (fir) {
|
||||||
is FirSimpleFunction -> createKFunctionType(fir, resultingReceiverType)
|
is FirSimpleFunction -> createKFunctionType(fir, resultingReceiverType, returnTypeRef)
|
||||||
is FirProperty -> createKPropertyType(fir, resultingReceiverType)
|
is FirProperty -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
||||||
else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}")
|
else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}")
|
||||||
}.let(candidate.substitutor::substituteOrSelf)
|
}.let(candidate.substitutor::substituteOrSelf)
|
||||||
|
|
||||||
@@ -224,9 +230,10 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
|||||||
|
|
||||||
private fun createKPropertyType(
|
private fun createKPropertyType(
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
receiverType: ConeKotlinType?
|
receiverType: ConeKotlinType?,
|
||||||
|
returnTypeRef: FirResolvedTypeRef
|
||||||
): ConeKotlinType {
|
): ConeKotlinType {
|
||||||
val propertyType = property.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for of $property")
|
val propertyType = returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for of $property")
|
||||||
return createKPropertyType(
|
return createKPropertyType(
|
||||||
receiverType, propertyType
|
receiverType, propertyType
|
||||||
)
|
)
|
||||||
@@ -234,7 +241,8 @@ private fun createKPropertyType(
|
|||||||
|
|
||||||
private fun createKFunctionType(
|
private fun createKFunctionType(
|
||||||
function: FirSimpleFunction,
|
function: FirSimpleFunction,
|
||||||
receiverType: ConeKotlinType?
|
receiverType: ConeKotlinType?,
|
||||||
|
returnTypeRef: FirResolvedTypeRef
|
||||||
): ConeKotlinType {
|
): ConeKotlinType {
|
||||||
val parameterTypes = function.valueParameters.map {
|
val parameterTypes = function.valueParameters.map {
|
||||||
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for parameter $it")
|
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for parameter $it")
|
||||||
@@ -242,7 +250,7 @@ private fun createKFunctionType(
|
|||||||
|
|
||||||
return createFunctionalType(
|
return createFunctionalType(
|
||||||
parameterTypes, receiverType = receiverType,
|
parameterTypes, receiverType = receiverType,
|
||||||
rawReturnType = function.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for return type of $function"),
|
rawReturnType = returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for return type of $function"),
|
||||||
isKFunctionType = true
|
isKFunctionType = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun <T, R> use(x: (T) -> R): (T) -> R = x
|
||||||
|
|
||||||
|
fun foo() = use(::bar)
|
||||||
|
fun bar(x: String) = 1
|
||||||
|
|
||||||
|
fun loop1() = use(::loop2)
|
||||||
|
fun loop2() = loop1()
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
FILE: implicitTypes.kt
|
||||||
|
public final fun <T, R> use(x: R|kotlin/Function1<T, R>|): R|kotlin/Function1<T, R>| {
|
||||||
|
^use R|<local>/x|
|
||||||
|
}
|
||||||
|
public final fun foo(): R|kotlin/Function1<kotlin/String, kotlin/Int>| {
|
||||||
|
^foo R|/use|<R|kotlin/String|, R|kotlin/Int|>(::R|/bar|)
|
||||||
|
}
|
||||||
|
public final fun bar(x: R|kotlin/String|): R|kotlin/Int| {
|
||||||
|
^bar Int(1)
|
||||||
|
}
|
||||||
|
public final fun loop1(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/use]> {
|
||||||
|
^loop1 <Inapplicable(INAPPLICABLE): [/use]>#(::loop2#)
|
||||||
|
}
|
||||||
|
public final fun loop2(): <ERROR TYPE REF: cycle> {
|
||||||
|
^loop2 R?C|/loop1|()
|
||||||
|
}
|
||||||
+5
@@ -55,6 +55,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/extensionReceiverInference.kt");
|
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/extensionReceiverInference.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("implicitTypes.kt")
|
||||||
|
public void testImplicitTypes() throws Exception {
|
||||||
|
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inferenceFromCallableReferenceType.kt")
|
@TestMetadata("inferenceFromCallableReferenceType.kt")
|
||||||
public void testInferenceFromCallableReferenceType() throws Exception {
|
public void testInferenceFromCallableReferenceType() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/inferenceFromCallableReferenceType.kt");
|
runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/inferenceFromCallableReferenceType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user