From 0e368cc23721cde39df80c28a0542bd915fc7df1 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Wed, 13 Jan 2021 21:13:48 +0300 Subject: [PATCH] FIR: Analyze return statements for implicit lambda with independent context --- .../body/resolve/BodyResolveContext.kt | 14 ++++++++++ .../body/resolve/FirBodyResolveTransformer.kt | 7 +++++ ...ControlFlowStatementsResolveTransformer.kt | 28 +++++++++++++------ .../FirDeclarationsResolveTransformer.kt | 6 +++- .../constraints/returnLambdaFromLambda.fir.kt | 2 +- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index e9254f795bb..8246c99fbc5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.sure @@ -56,6 +57,8 @@ class BodyResolveContext( @set:PrivateForInline var inferenceSession: FirInferenceSession = FirInferenceSession.DEFAULT + val anonymousFunctionsAnalyzedInDependentContext: MutableSet> = mutableSetOf() + @OptIn(PrivateForInline::class) inline fun withInferenceSession(inferenceSession: FirInferenceSession, block: () -> R): R { val oldSession = this.inferenceSession @@ -125,6 +128,16 @@ class BodyResolveContext( } } + @OptIn(PrivateForInline::class) + inline fun withLambdaBeingAnalyzedInDependentContext(lambda: FirAnonymousFunctionSymbol, l: () -> R): R { + anonymousFunctionsAnalyzedInDependentContext.add(lambda) + return try { + l() + } finally { + anonymousFunctionsAnalyzedInDependentContext.remove(lambda) + } + } + @OptIn(PrivateForInline::class) fun replaceTowerDataContext(newContext: FirTowerDataContext) { towerDataContext = newContext @@ -189,5 +202,6 @@ class BodyResolveContext( towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions) containers = this@BodyResolveContext.containers towerDataContext = this@BodyResolveContext.towerDataContext + anonymousFunctionsAnalyzedInDependentContext.addAll(this@BodyResolveContext.anonymousFunctionsAnalyzedInDependentContext) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index 3243455d96b..ea09b540c33 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -342,6 +342,13 @@ open class FirBodyResolveTransformer( return controlFlowStatementsTransformer.transformJump(jump, data) } + override fun transformReturnExpression( + returnExpression: FirReturnExpression, + data: ResolutionMode + ): CompositeTransformResult { + return controlFlowStatementsTransformer.transformReturnExpression(returnExpression, data) + } + override fun transformThrowExpression( throwExpression: FirThrowExpression, data: ResolutionMode diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 3618d271e6c..3864150cf6e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -187,18 +187,30 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran // ------------------------------- Jumps ------------------------------- override fun transformJump(jump: FirJump, data: ResolutionMode): CompositeTransformResult { - val expectedTypeRef = (jump as? FirReturnExpression)?.target?.labeledElement?.returnTypeRef - - val mode = if (expectedTypeRef != null) { - ResolutionMode.WithExpectedType(expectedTypeRef) - } else { - ResolutionMode.ContextIndependent - } - val result = transformer.transformExpression(jump, mode).single + val result = transformer.transformExpression(jump, data).single dataFlowAnalyzer.exitJump(jump) return result.compose() } + override fun transformReturnExpression( + returnExpression: FirReturnExpression, + data: ResolutionMode + ): CompositeTransformResult { + val labeledElement = returnExpression.target.labeledElement + val expectedTypeRef = labeledElement.returnTypeRef + @Suppress("IntroduceWhenSubject") + val mode = when { + labeledElement.symbol in context.anonymousFunctionsAnalyzedInDependentContext -> { + ResolutionMode.ContextDependent + } + else -> { + ResolutionMode.WithExpectedType(expectedTypeRef) + } + } + + return transformJump(returnExpression, mode) + } + override fun transformThrowExpression( throwExpression: FirThrowExpression, data: ResolutionMode diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index b160becbf98..557eff9e2a3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -435,7 +435,11 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor fun transform(): FirAnonymousFunction { val expectedReturnType = lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef } - val result = transformFunction(anonymousFunction, withExpectedType(expectedReturnType)).single as FirAnonymousFunction + + val result = context.withLambdaBeingAnalyzedInDependentContext(anonymousFunction.symbol) { + transformFunction(anonymousFunction, withExpectedType(expectedReturnType)).single as FirAnonymousFunction + } + val body = result.body if (result.returnTypeRef is FirImplicitTypeRef && body != null) { result.transformReturnTypeRef(transformer, withExpectedType(body.resultType)) diff --git a/compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.fir.kt b/compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.fir.kt index 0f100c7b735..f79f1fa6a01 100644 --- a/compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.fir.kt @@ -3,7 +3,7 @@ fun testLambda() { val basicTest: (Int) -> Int = myRun { val x: Any? = null - if (x is String) return@myRun { it -> x.length + it } + if (x is String) return@myRun { it -> x.length + it } if (x !is Int) return@myRun { it -> it } { it -> x + it }