[FIR] Don't pass flow from inplace lambdas while resolve delegates
#KT-36248
This commit is contained in:
@@ -163,6 +163,16 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
return graph
|
return graph
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------- Delegate -----------------------------------
|
||||||
|
|
||||||
|
fun enterDelegateExpression() {
|
||||||
|
graphBuilder.enterDelegateExpression()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exitDelegateExpression() {
|
||||||
|
graphBuilder.exitDelegateExpression()
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Block -----------------------------------
|
// ----------------------------------- Block -----------------------------------
|
||||||
|
|
||||||
fun enterBlock(block: FirBlock) {
|
fun enterBlock(block: FirBlock) {
|
||||||
|
|||||||
+13
-1
@@ -58,6 +58,7 @@ class ControlFlowGraphBuilder {
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
private var idCounter: Int = 0
|
private var idCounter: Int = 0
|
||||||
|
private val shouldPassFlowFromInplaceLambda: Stack<Boolean> = stackOf(true)
|
||||||
|
|
||||||
fun createId(): Int = idCounter++
|
fun createId(): Int = idCounter++
|
||||||
|
|
||||||
@@ -142,7 +143,7 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
if (postponedExitNode != null) {
|
if (postponedExitNode != null) {
|
||||||
CFGNode.addEdge(lastNodes.pop(), postponedExitNode, propagateDeadness = true, kind = EdgeKind.Cfg)
|
CFGNode.addEdge(lastNodes.pop(), postponedExitNode, propagateDeadness = true, kind = EdgeKind.Cfg)
|
||||||
if (invocationKind == InvocationKind.EXACTLY_ONCE) {
|
if (invocationKind == InvocationKind.EXACTLY_ONCE && shouldPassFlowFromInplaceLambda.top()) {
|
||||||
exitsFromCompletedPostponedAnonymousFunctions += postponedExitNode
|
exitsFromCompletedPostponedAnonymousFunctions += postponedExitNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,6 +263,16 @@ class ControlFlowGraphBuilder {
|
|||||||
return topLevelVariableExitNode to graphs.pop()
|
return topLevelVariableExitNode to graphs.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------- Delegate -----------------------------------
|
||||||
|
|
||||||
|
fun enterDelegateExpression() {
|
||||||
|
shouldPassFlowFromInplaceLambda.push(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exitDelegateExpression() {
|
||||||
|
shouldPassFlowFromInplaceLambda.pop()
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Operator call -----------------------------------
|
// ----------------------------------- Operator call -----------------------------------
|
||||||
|
|
||||||
fun exitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall): TypeOperatorCallNode {
|
fun exitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall): TypeOperatorCallNode {
|
||||||
@@ -639,6 +650,7 @@ class ControlFlowGraphBuilder {
|
|||||||
node: CFGNode<*>,
|
node: CFGNode<*>,
|
||||||
callCompleted: Boolean
|
callCompleted: Boolean
|
||||||
): Pair<EdgeKind, UnionFunctionCallArgumentsNode?> {
|
): Pair<EdgeKind, UnionFunctionCallArgumentsNode?> {
|
||||||
|
if (!shouldPassFlowFromInplaceLambda.top()) return EdgeKind.Simple to null
|
||||||
var kind = EdgeKind.Simple
|
var kind = EdgeKind.Simple
|
||||||
if (!callCompleted || exitsFromCompletedPostponedAnonymousFunctions.isEmpty()) {
|
if (!callCompleted || exitsFromCompletedPostponedAnonymousFunctions.isEmpty()) {
|
||||||
return EdgeKind.Simple to null
|
return EdgeKind.Simple to null
|
||||||
|
|||||||
+14
-9
@@ -161,18 +161,23 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
|||||||
wrappedDelegateExpression: FirWrappedDelegateExpression,
|
wrappedDelegateExpression: FirWrappedDelegateExpression,
|
||||||
data: ResolutionMode,
|
data: ResolutionMode,
|
||||||
): CompositeTransformResult<FirStatement> {
|
): CompositeTransformResult<FirStatement> {
|
||||||
val delegateProvider = wrappedDelegateExpression.delegateProvider.transformSingle(transformer, ResolutionMode.ContextDependent)
|
dataFlowAnalyzer.enterDelegateExpression()
|
||||||
when (val calleeReference = (delegateProvider as FirResolvable).calleeReference) {
|
try {
|
||||||
is FirResolvedNamedReference -> return delegateProvider.compose()
|
val delegateProvider = wrappedDelegateExpression.delegateProvider.transformSingle(transformer, ResolutionMode.ContextDependent)
|
||||||
is FirNamedReferenceWithCandidate -> {
|
when (val calleeReference = (delegateProvider as FirResolvable).calleeReference) {
|
||||||
val candidate = calleeReference.candidate
|
is FirResolvedNamedReference -> return delegateProvider.compose()
|
||||||
if (!candidate.system.hasContradiction) {
|
is FirNamedReferenceWithCandidate -> {
|
||||||
return delegateProvider.compose()
|
val candidate = calleeReference.candidate
|
||||||
|
if (!candidate.system.hasContradiction) {
|
||||||
|
return delegateProvider.compose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedDelegateExpression.expression.transform(transformer, ResolutionMode.ContextDependent)
|
return wrappedDelegateExpression.expression.transform(transformer, ResolutionMode.ContextDependent)
|
||||||
|
} finally {
|
||||||
|
dataFlowAnalyzer.exitDelegateExpression()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformLocalVariable(variable: FirProperty): CompositeTransformResult<FirProperty> {
|
private fun transformLocalVariable(variable: FirProperty): CompositeTransformResult<FirProperty> {
|
||||||
|
|||||||
+20
-17
@@ -27,8 +27,9 @@ digraph postponedLambdaInConstructor_kt {
|
|||||||
}
|
}
|
||||||
10 [label="Postponed exit from lambda"];
|
10 [label="Postponed exit from lambda"];
|
||||||
11 [label="Function call: R|<local>/s|.R|kotlin/let|<R|kotlin/String|, R|() -> kotlin/String|>(...)"];
|
11 [label="Function call: R|<local>/s|.R|kotlin/let|<R|kotlin/String|, R|() -> kotlin/String|>(...)"];
|
||||||
12 [label="Delegated constructor call: super<R|A|>(...)"];
|
12 [label="Call arguments union" style="filled" fillcolor=yellow];
|
||||||
13 [label="Exit function <init>" style="filled" fillcolor=red];
|
13 [label="Delegated constructor call: super<R|A|>(...)"];
|
||||||
|
14 [label="Exit function <init>" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
3 -> {4};
|
3 -> {4};
|
||||||
@@ -39,46 +40,48 @@ digraph postponedLambdaInConstructor_kt {
|
|||||||
7 -> {8 8} [color=green];
|
7 -> {8 8} [color=green];
|
||||||
8 -> {9};
|
8 -> {9};
|
||||||
9 -> {10} [color=green];
|
9 -> {10} [color=green];
|
||||||
|
9 -> {12} [color=red];
|
||||||
10 -> {11};
|
10 -> {11};
|
||||||
11 -> {12};
|
11 -> {12};
|
||||||
12 -> {13};
|
12 -> {13};
|
||||||
|
13 -> {14};
|
||||||
|
|
||||||
subgraph cluster_3 {
|
subgraph cluster_3 {
|
||||||
color=red
|
color=red
|
||||||
14 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
|
15 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
|
||||||
15 [label="Access variable R|<local>/it|"];
|
16 [label="Access variable R|<local>/it|"];
|
||||||
16 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
17 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
14 -> {15};
|
|
||||||
15 -> {16};
|
15 -> {16};
|
||||||
|
16 -> {17};
|
||||||
|
|
||||||
subgraph cluster_4 {
|
subgraph cluster_4 {
|
||||||
color=red
|
color=red
|
||||||
17 [label="Enter function getter" style="filled" fillcolor=red];
|
18 [label="Enter function getter" style="filled" fillcolor=red];
|
||||||
18 [label="Exit function getter" style="filled" fillcolor=red];
|
19 [label="Exit function getter" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
17 -> {18};
|
18 -> {19};
|
||||||
|
|
||||||
subgraph cluster_5 {
|
subgraph cluster_5 {
|
||||||
color=red
|
color=red
|
||||||
19 [label="Enter property" style="filled" fillcolor=red];
|
20 [label="Enter property" style="filled" fillcolor=red];
|
||||||
20 [label="Access variable R|<local>/s|"];
|
21 [label="Access variable R|<local>/s|"];
|
||||||
21 [label="Exit property" style="filled" fillcolor=red];
|
22 [label="Exit property" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
19 -> {20};
|
|
||||||
20 -> {21};
|
20 -> {21};
|
||||||
|
21 -> {22};
|
||||||
|
|
||||||
subgraph cluster_6 {
|
subgraph cluster_6 {
|
||||||
color=red
|
color=red
|
||||||
22 [label="Enter function foo" style="filled" fillcolor=red];
|
23 [label="Enter function foo" style="filled" fillcolor=red];
|
||||||
23 [label="Function call: this@R|/B|.R|/B.foo|()"];
|
24 [label="Function call: this@R|/B|.R|/B.foo|()"];
|
||||||
24 [label="Exit function foo" style="filled" fillcolor=red];
|
25 [label="Exit function foo" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
22 -> {23};
|
|
||||||
23 -> {24};
|
23 -> {24};
|
||||||
|
24 -> {25};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user