From 9c3117ba40a909da3adb73974c1782ba34f05c97 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 26 Nov 2019 15:18:18 +0300 Subject: [PATCH] [FIR] Git rid of creating new when and try fir nodes It's necessary because of before change we safe original `when` without infered type as return statement of lambda and after that we add incorrect constraint system from it to outer call --- ...rCallCompletionResultsWriterTransformer.kt | 17 ++++---- .../transformers/FirSyntheticCallGenerator.kt | 19 ++++++++- .../stdlib/whenAsLambdaReturnStatement.kt | 21 ++++++++++ .../stdlib/whenAsLambdaReturnStatement.txt | 39 +++++++++++++++++++ ...FirDiagnosticsWithStdlibTestGenerated.java | 5 +++ 5 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.kt create mode 100644 compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index d0f3c43eab1..41c9e350ea4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -219,11 +219,11 @@ class FirCallCompletionResultsWriterTransformer( val initialType = subCandidate.substitutor.substituteOrNull(typeRef.type) val finalType = finalSubstitutor.substituteOrNull(initialType) - val resultType = typeRef.withReplacedConeType(finalType) + whenExpression.resultType = typeRef.withReplacedConeType(finalType) - return whenExpression.copy( - resultType = resultType, - calleeReference = FirResolvedNamedReferenceImpl( + return whenExpression.transformCalleeReference( + StoreCalleeReference, + FirResolvedNamedReferenceImpl( calleeReference.source, calleeReference.name, calleeReference.candidateSymbol @@ -245,11 +245,10 @@ class FirCallCompletionResultsWriterTransformer( val initialType = subCandidate.substitutor.substituteOrNull(typeRef.type) val finalType = finalSubstitutor.substituteOrNull(initialType) - val resultType = typeRef.withReplacedConeType(finalType) - - return tryExpression.copy( - resultType = resultType, - calleeReference = FirResolvedNamedReferenceImpl( + tryExpression.resultType = typeRef.withReplacedConeType(finalType) + return tryExpression.transformCalleeReference( + StoreCalleeReference, + FirResolvedNamedReferenceImpl( calleeReference.source, calleeReference.name, calleeReference.candidateSymbol diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index dd81b0a1e67..5a5d103b67d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.copy import org.jetbrains.kotlin.fir.declarations.FirResolvePhase @@ -19,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl +import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.impl.FirStubReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.calls.* @@ -34,6 +36,9 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirTypeProjectionWithVarianceImpl +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.types.Variance @@ -59,7 +64,7 @@ class FirSyntheticCallGenerator( SyntheticCallableId.WHEN.callableName ) ?: return null // TODO - return whenExpression.copy(calleeReference = reference) + return whenExpression.transformCalleeReference(UpdateReference, reference) } fun generateCalleeForTryExpression(tryExpression: FirTryExpression): FirTryExpression? { @@ -81,7 +86,7 @@ class FirSyntheticCallGenerator( SyntheticCallableId.TRY.callableName ) ?: return null // TODO - return tryExpression.copy(calleeReference = reference) + return tryExpression.transformCalleeReference(UpdateReference, reference) } fun resolveCallableReferenceWithSyntheticOuterCall( @@ -193,3 +198,13 @@ class FirSyntheticCallGenerator( } } } + +private object UpdateReference : FirTransformer() { + override fun transformElement(element: E, data: FirNamedReferenceWithCandidate): CompositeTransformResult { + return element.compose() + } + + override fun transformReference(reference: FirReference, data: FirNamedReferenceWithCandidate): CompositeTransformResult { + return data.compose() + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.kt b/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.kt new file mode 100644 index 00000000000..3d83bd317ee --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.kt @@ -0,0 +1,21 @@ +class Module + +fun getModule(): Module? = null + +fun getInt(): Int? = null + +fun test_1(modules: Collection, b: Boolean) { + val res = modules.groupBy { module -> + if (b) module else module + } +} + +fun test_2() { + val x = run { + try { + "" + } finally { + getInt() + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.txt b/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.txt new file mode 100644 index 00000000000..505cd7ba472 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.txt @@ -0,0 +1,39 @@ +FILE: whenAsLambdaReturnStatement.kt + public final class Module : R|kotlin/Any| { + public constructor(): R|Module| { + super() + } + + } + public final fun getModule(): R|Module?| { + ^getModule Null(null) + } + public final fun getInt(): R|kotlin/Int?| { + ^getInt Null(null) + } + public final fun test_1(modules: R|kotlin/collections/Collection|, b: R|kotlin/Boolean|): R|kotlin/Unit| { + lval res: R|kotlin/collections/Map>| = R|/modules|.R|kotlin/collections/groupBy|( = groupBy@fun (module: R|Module|): R|Module| { + when () { + R|/b| -> { + R|/module| + } + else -> { + R|/module| + } + } + + } + ) + } + public final fun test_2(): R|kotlin/Unit| { + lval x: R|kotlin/String| = R|kotlin/run|( = run@fun (): R|kotlin/String| { + try { + String() + } + finally { + R|/getInt|() + } + + } + ) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 217367ecac7..f469e46b198 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -183,6 +183,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic runTest("compiler/fir/resolve/testData/resolve/stdlib/unaryOperators.kt"); } + @TestMetadata("whenAsLambdaReturnStatement.kt") + public void testWhenAsLambdaReturnStatement() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/stdlib/whenAsLambdaReturnStatement.kt"); + } + @TestMetadata("compiler/fir/resolve/testData/resolve/stdlib/callableReferences") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)