FIR CFG: join/unify data flow from postponed lambdas at each level
For example:
foo(
// `if` joins A & B
if (condition)
run { ... } // A
else
run { ... }, // B
run { ... } // C
) // `foo` unifies `A & B` and `C`, so if it is not resolved itself,
// further `if`s, `when`s, safe calls outside it, etc. continue
// building the correct type predicate until the next completed
// call.
^KT-44512 Fixed
This commit is contained in:
@@ -228,17 +228,25 @@ class PostponedLambdaEnterNode(owner: ControlFlowGraph, override val fir: FirAno
|
||||
return visitor.visitPostponedLambdaEnterNode(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
class PostponedLambdaExitNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunctionExpression, level: Int, id: Int) : CFGNode<FirAnonymousFunctionExpression>(owner, level, id) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
return visitor.visitPostponedLambdaExitNode(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
class UnionFunctionCallArgumentsNode(owner: ControlFlowGraph, override val fir: FirElement, level: Int, id: Int) : CFGNode<FirElement>(owner, level, id) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
return visitor.visitUnionFunctionCallArgumentsNode(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
class MergePostponedLambdaExitsNode(owner: ControlFlowGraph, override val fir: FirElement, level: Int, id: Int) : CFGNode<FirElement>(owner, level, id) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
return visitor.visitMergePostponedLambdaExitsNode(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
class AnonymousFunctionExpressionExitNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunctionExpression, level: Int, id: Int) : CFGNode<FirAnonymousFunctionExpression>(owner, level, id) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
return visitor.visitAnonymousFunctionExpressionExitNode(this, data)
|
||||
|
||||
@@ -107,6 +107,7 @@ fun CFGNode<*>.render(): String =
|
||||
is AnonymousFunctionExpressionExitNode -> "Exit anonymous function expression"
|
||||
|
||||
is UnionFunctionCallArgumentsNode -> "Call arguments union"
|
||||
is MergePostponedLambdaExitsNode -> "Merge postponed lambda exits"
|
||||
|
||||
is ClassEnterNode -> "Enter class ${owner.name}"
|
||||
is ClassExitNode -> "Exit class ${owner.name}"
|
||||
|
||||
+4
@@ -46,6 +46,10 @@ abstract class ControlFlowGraphVisitor<out R, in D> {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitMergePostponedLambdaExitsNode(node: MergePostponedLambdaExitsNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitAnonymousFunctionExpressionExitNode(node: AnonymousFunctionExpressionExitNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
+8
@@ -32,6 +32,10 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
||||
visitNode(node)
|
||||
}
|
||||
|
||||
open fun visitMergePostponedLambdaExitsNode(node: MergePostponedLambdaExitsNode) {
|
||||
visitNode(node)
|
||||
}
|
||||
|
||||
// ----------------------------------- Anonymous object -----------------------------------
|
||||
|
||||
open fun visitAnonymousObjectExitNode(node: AnonymousObjectExitNode) {
|
||||
@@ -325,6 +329,10 @@ abstract class ControlFlowGraphVisitorVoid : ControlFlowGraphVisitor<Unit, Nothi
|
||||
visitUnionFunctionCallArgumentsNode(node)
|
||||
}
|
||||
|
||||
final override fun visitMergePostponedLambdaExitsNode(node: MergePostponedLambdaExitsNode, data: Nothing?) {
|
||||
visitMergePostponedLambdaExitsNode(node)
|
||||
}
|
||||
|
||||
// ----------------------------------- Anonymous object -----------------------------------
|
||||
|
||||
final override fun visitAnonymousObjectExitNode(node: AnonymousObjectExitNode, data: Nothing?) {
|
||||
|
||||
Reference in New Issue
Block a user