From 152236d84ac4086261ac229e3033b9bae2bcb938 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 22 Oct 2019 16:06:42 +0300 Subject: [PATCH] FIR: Support callable references to declarations with implicit types ^KT-32725 In Progress --- .../kotlin/fir/resolve/calls/ResolverParts.kt | 22 +++++++++++++------ .../callableReferences/implicitTypes.kt | 7 ++++++ .../callableReferences/implicitTypes.txt | 16 ++++++++++++++ .../fir/FirDiagnosticsTestGenerated.java | 5 +++++ 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index ffb39666265..d147490ba66 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -176,16 +176,22 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { val outerCsBuilder = callInfo.outerCSBuilder ?: return val expectedType = callInfo.expectedType ?: return + val candidateSymbol = candidate.symbol as? FirCallableSymbol<*> ?: return val resultingReceiverType = when (callInfo.lhs) { is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier } 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) { - is FirSimpleFunction -> createKFunctionType(fir, resultingReceiverType) - is FirProperty -> createKPropertyType(fir, resultingReceiverType) + is FirSimpleFunction -> createKFunctionType(fir, resultingReceiverType, returnTypeRef) + is FirProperty -> createKPropertyType(fir, resultingReceiverType, returnTypeRef) else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}") }.let(candidate.substitutor::substituteOrSelf) @@ -224,9 +230,10 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() { private fun createKPropertyType( property: FirProperty, - receiverType: ConeKotlinType? + receiverType: ConeKotlinType?, + returnTypeRef: FirResolvedTypeRef ): ConeKotlinType { - val propertyType = property.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for of $property") + val propertyType = returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for of $property") return createKPropertyType( receiverType, propertyType ) @@ -234,7 +241,8 @@ private fun createKPropertyType( private fun createKFunctionType( function: FirSimpleFunction, - receiverType: ConeKotlinType? + receiverType: ConeKotlinType?, + returnTypeRef: FirResolvedTypeRef ): ConeKotlinType { val parameterTypes = function.valueParameters.map { it.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for parameter $it") @@ -242,7 +250,7 @@ private fun createKFunctionType( return createFunctionalType( 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 ) } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.kt new file mode 100644 index 00000000000..15f33aa2ca4 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.kt @@ -0,0 +1,7 @@ +fun use(x: (T) -> R): (T) -> R = x + +fun foo() = use(::bar) +fun bar(x: String) = 1 + +fun loop1() = use(::loop2) +fun loop2() = loop1() diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.txt new file mode 100644 index 00000000000..72b99e9ca86 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/implicitTypes.txt @@ -0,0 +1,16 @@ +FILE: implicitTypes.kt + public final fun use(x: R|kotlin/Function1|): R|kotlin/Function1| { + ^use R|/x| + } + public final fun foo(): R|kotlin/Function1| { + ^foo R|/use|(::R|/bar|) + } + public final fun bar(x: R|kotlin/String|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun loop1(): { + ^loop1 #(::loop2#) + } + public final fun loop2(): { + ^loop2 R?C|/loop1|() + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 2a5593cacec..037d3e8c7d5 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -55,6 +55,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { 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") public void testInferenceFromCallableReferenceType() throws Exception { runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/inferenceFromCallableReferenceType.kt");