FIR: Analyze return statements for implicit lambda with independent context
This commit is contained in:
+14
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
|||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
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.name.Name
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
|
|
||||||
@@ -56,6 +57,8 @@ class BodyResolveContext(
|
|||||||
@set:PrivateForInline
|
@set:PrivateForInline
|
||||||
var inferenceSession: FirInferenceSession = FirInferenceSession.DEFAULT
|
var inferenceSession: FirInferenceSession = FirInferenceSession.DEFAULT
|
||||||
|
|
||||||
|
val anonymousFunctionsAnalyzedInDependentContext: MutableSet<FirFunctionSymbol<*>> = mutableSetOf()
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <R> withInferenceSession(inferenceSession: FirInferenceSession, block: () -> R): R {
|
inline fun <R> withInferenceSession(inferenceSession: FirInferenceSession, block: () -> R): R {
|
||||||
val oldSession = this.inferenceSession
|
val oldSession = this.inferenceSession
|
||||||
@@ -125,6 +128,16 @@ class BodyResolveContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(PrivateForInline::class)
|
||||||
|
inline fun <R> withLambdaBeingAnalyzedInDependentContext(lambda: FirAnonymousFunctionSymbol, l: () -> R): R {
|
||||||
|
anonymousFunctionsAnalyzedInDependentContext.add(lambda)
|
||||||
|
return try {
|
||||||
|
l()
|
||||||
|
} finally {
|
||||||
|
anonymousFunctionsAnalyzedInDependentContext.remove(lambda)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
fun replaceTowerDataContext(newContext: FirTowerDataContext) {
|
fun replaceTowerDataContext(newContext: FirTowerDataContext) {
|
||||||
towerDataContext = newContext
|
towerDataContext = newContext
|
||||||
@@ -189,5 +202,6 @@ class BodyResolveContext(
|
|||||||
towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions)
|
towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions)
|
||||||
containers = this@BodyResolveContext.containers
|
containers = this@BodyResolveContext.containers
|
||||||
towerDataContext = this@BodyResolveContext.towerDataContext
|
towerDataContext = this@BodyResolveContext.towerDataContext
|
||||||
|
anonymousFunctionsAnalyzedInDependentContext.addAll(this@BodyResolveContext.anonymousFunctionsAnalyzedInDependentContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -342,6 +342,13 @@ open class FirBodyResolveTransformer(
|
|||||||
return controlFlowStatementsTransformer.transformJump(jump, data)
|
return controlFlowStatementsTransformer.transformJump(jump, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformReturnExpression(
|
||||||
|
returnExpression: FirReturnExpression,
|
||||||
|
data: ResolutionMode
|
||||||
|
): CompositeTransformResult<FirStatement> {
|
||||||
|
return controlFlowStatementsTransformer.transformReturnExpression(returnExpression, data)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transformThrowExpression(
|
override fun transformThrowExpression(
|
||||||
throwExpression: FirThrowExpression,
|
throwExpression: FirThrowExpression,
|
||||||
data: ResolutionMode
|
data: ResolutionMode
|
||||||
|
|||||||
+20
-8
@@ -187,18 +187,30 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
// ------------------------------- Jumps -------------------------------
|
// ------------------------------- Jumps -------------------------------
|
||||||
|
|
||||||
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
||||||
val expectedTypeRef = (jump as? FirReturnExpression)?.target?.labeledElement?.returnTypeRef
|
val result = transformer.transformExpression(jump, data).single
|
||||||
|
|
||||||
val mode = if (expectedTypeRef != null) {
|
|
||||||
ResolutionMode.WithExpectedType(expectedTypeRef)
|
|
||||||
} else {
|
|
||||||
ResolutionMode.ContextIndependent
|
|
||||||
}
|
|
||||||
val result = transformer.transformExpression(jump, mode).single
|
|
||||||
dataFlowAnalyzer.exitJump(jump)
|
dataFlowAnalyzer.exitJump(jump)
|
||||||
return result.compose()
|
return result.compose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformReturnExpression(
|
||||||
|
returnExpression: FirReturnExpression,
|
||||||
|
data: ResolutionMode
|
||||||
|
): CompositeTransformResult<FirStatement> {
|
||||||
|
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(
|
override fun transformThrowExpression(
|
||||||
throwExpression: FirThrowExpression,
|
throwExpression: FirThrowExpression,
|
||||||
data: ResolutionMode
|
data: ResolutionMode
|
||||||
|
|||||||
+5
-1
@@ -435,7 +435,11 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
fun transform(): FirAnonymousFunction {
|
fun transform(): FirAnonymousFunction {
|
||||||
val expectedReturnType =
|
val expectedReturnType =
|
||||||
lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
|
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
|
val body = result.body
|
||||||
if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
||||||
result.transformReturnTypeRef(transformer, withExpectedType(body.resultType))
|
result.transformReturnTypeRef(transformer, withExpectedType(body.resultType))
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
fun testLambda() {
|
fun testLambda() {
|
||||||
val basicTest: (Int) -> Int = myRun {
|
val basicTest: (Int) -> Int = myRun {
|
||||||
val x: Any? = null
|
val x: Any? = null
|
||||||
if (x is String) return@myRun { it -> x.length <!AMBIGUITY!>+<!> it }
|
if (x is String) return@myRun { it -> x.length + it }
|
||||||
if (x !is Int) return@myRun { it -> it }
|
if (x !is Int) return@myRun { it -> it }
|
||||||
|
|
||||||
{ it -> x + it }
|
{ it -> x + it }
|
||||||
|
|||||||
Reference in New Issue
Block a user