From 4c6eff91744f9a9e3e225d3bd6e9bd7450b621cf Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 9 Dec 2022 14:11:12 +0100 Subject: [PATCH] FIR CFA: compute subgraph relationships automatically No more `addSubGraph`. Also no more `owner` in graphs. ^KT-40526 Obsolete ^KT-40582 Obsolete --- .../testData/resolve/cfg/defaultArguments.dot | 4 +- .../resolve/cfg/flowFromInplaceLambda2.dot | 78 +++++++++---------- .../smartcasts/lambdas/lambdaInWhenBranch.dot | 2 +- .../ControlFlowAnalysisDiagnosticComponent.kt | 2 +- .../dfa/cfg/ControlFlowGraphBuilder.kt | 31 ++------ .../dfa/cfg/ControlFlowGraphRenderer.kt | 2 +- .../kotlin/fir/resolve/dfa/cfg/CFGNode.kt | 24 +++--- .../fir/resolve/dfa/cfg/ControlFlowGraph.kt | 41 ++-------- .../codegen/box/smartCasts/kt44814.dot | 54 ++++++------- 9 files changed, 97 insertions(+), 141 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/defaultArguments.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/defaultArguments.dot index 98fb2ece612..ea0e03441a7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/defaultArguments.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/defaultArguments.dot @@ -67,10 +67,10 @@ digraph defaultArguments_kt { } 7 -> {8}; 8 -> {9 16}; - 8 -> {16 16} [style=dashed]; + 8 -> {16} [style=dashed]; 9 -> {10}; 10 -> {11 20}; - 10 -> {20 20} [style=dashed]; + 10 -> {20} [style=dashed]; 11 -> {12}; 12 -> {13}; 13 -> {14}; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot index c2e05369bd1..5f61e3000f4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot @@ -426,14 +426,14 @@ digraph flowFromInplaceLambda2_kt { 153 [label="Postponed enter to lambda"]; subgraph cluster_40 { color=blue - 187 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 180 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_41 { color=blue - 188 [label="Enter block"]; - 189 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 190 [label="Exit block"]; + 181 [label="Enter block"]; + 182 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 183 [label="Exit block"]; } - 191 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 184 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 154 [label="Postponed exit from lambda"]; 155 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; @@ -447,16 +447,16 @@ digraph flowFromInplaceLambda2_kt { 160 [label="Postponed enter to lambda"]; subgraph cluster_43 { color=blue - 180 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 185 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_44 { color=blue - 181 [label="Enter block"]; - 182 [label="Const: Null(null)"]; - 183 [label="Assignment: R|/p|"]; - 184 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 185 [label="Exit block"]; + 186 [label="Enter block"]; + 187 [label="Const: Null(null)"]; + 188 [label="Assignment: R|/p|"]; + 189 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 190 [label="Exit block"]; } - 186 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 191 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 161 [label="Postponed exit from lambda"]; 162 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; @@ -518,9 +518,9 @@ digraph flowFromInplaceLambda2_kt { 150 -> {151}; 151 -> {152}; 152 -> {153}; - 153 -> {155 187}; + 153 -> {155 180}; 153 -> {154} [style=dotted]; - 153 -> {187} [style=dashed]; + 153 -> {180} [style=dashed]; 154 -> {155} [color=green]; 154 -> {171} [color=red]; 155 -> {156}; @@ -528,9 +528,9 @@ digraph flowFromInplaceLambda2_kt { 157 -> {165}; 158 -> {159}; 159 -> {160}; - 160 -> {162 180}; + 160 -> {162 185}; 160 -> {161} [style=dotted]; - 160 -> {180} [style=dashed]; + 160 -> {185} [style=dashed]; 161 -> {162} [color=green]; 161 -> {171} [color=red]; 162 -> {163}; @@ -557,14 +557,14 @@ digraph flowFromInplaceLambda2_kt { 181 -> {182}; 182 -> {183}; 183 -> {184}; - 184 -> {185}; + 184 -> {154}; 185 -> {186}; - 186 -> {161}; + 186 -> {187}; 187 -> {188}; 188 -> {189}; 189 -> {190}; 190 -> {191}; - 191 -> {154}; + 191 -> {161}; 192 -> {193}; 193 -> {194}; 194 -> {195}; @@ -685,16 +685,16 @@ digraph flowFromInplaceLambda2_kt { 240 [label="Postponed enter to lambda"]; subgraph cluster_59 { color=blue - 271 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 264 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_60 { color=blue - 272 [label="Enter block"]; - 273 [label="Access variable R|/x|"]; - 274 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 275 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 276 [label="Exit block"]; + 265 [label="Enter block"]; + 266 [label="Access variable R|/x|"]; + 267 [label="Type operator: (R|/x| as R|kotlin/String|)"]; + 268 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 269 [label="Exit block"]; } - 277 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 270 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 241 [label="Postponed exit from lambda"]; 242 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; @@ -708,16 +708,16 @@ digraph flowFromInplaceLambda2_kt { 247 [label="Postponed enter to lambda"]; subgraph cluster_62 { color=blue - 264 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 271 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_63 { color=blue - 265 [label="Enter block"]; - 266 [label="Access variable R|/x|"]; - 267 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 268 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 269 [label="Exit block"]; + 272 [label="Enter block"]; + 273 [label="Access variable R|/x|"]; + 274 [label="Type operator: (R|/x| as R|kotlin/String|)"]; + 275 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 276 [label="Exit block"]; } - 270 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 277 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 248 [label="Postponed exit from lambda"]; 249 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; @@ -762,9 +762,9 @@ digraph flowFromInplaceLambda2_kt { 237 -> {238}; 238 -> {239}; 239 -> {240}; - 240 -> {242 271}; + 240 -> {242 264}; 240 -> {241} [style=dotted]; - 240 -> {271} [style=dashed]; + 240 -> {264} [style=dashed]; 241 -> {242} [color=green]; 241 -> {258} [color=red]; 242 -> {243}; @@ -772,9 +772,9 @@ digraph flowFromInplaceLambda2_kt { 244 -> {252}; 245 -> {246}; 246 -> {247}; - 247 -> {249 264}; + 247 -> {249 271}; 247 -> {248} [style=dotted]; - 247 -> {264} [style=dashed]; + 247 -> {271} [style=dashed]; 248 -> {249} [color=green]; 248 -> {258} [color=red]; 249 -> {250}; @@ -800,14 +800,14 @@ digraph flowFromInplaceLambda2_kt { 267 -> {268}; 268 -> {269}; 269 -> {270}; - 270 -> {248}; + 270 -> {241}; 271 -> {272}; 272 -> {273}; 273 -> {274}; 274 -> {275}; 275 -> {276}; 276 -> {277}; - 277 -> {241}; + 277 -> {248}; 278 -> {279}; 279 -> {280}; 280 -> {281}; diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/lambdas/lambdaInWhenBranch.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/lambdas/lambdaInWhenBranch.dot index fa59369ab18..8685b5b3fad 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/lambdas/lambdaInWhenBranch.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/lambdas/lambdaInWhenBranch.dot @@ -70,7 +70,7 @@ digraph lambdaInWhenBranch_kt { 11 -> {12}; 13 -> {14}; 14 -> {15 17}; - 14 -> {17 17} [style=dashed]; + 14 -> {17} [style=dashed]; 15 -> {16}; 17 -> {18}; 18 -> {19}; diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt index 46ac55b74b8..258cfe09ee8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt @@ -25,7 +25,7 @@ class ControlFlowAnalysisDiagnosticComponent( private fun analyze(declaration: FirControlFlowGraphOwner, context: CheckerContext) { val graph = declaration.controlFlowGraphReference?.controlFlowGraph ?: return - if (graph.owner != null) return + if (graph.isSubGraph) return cfaCheckers.forEach { it.analyze(graph, reporter, context) } val (properties, capturedWrites) = LocalPropertyAndCapturedWriteCollector.collect(graph) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index c5ce717c0b7..c9c005e4cb1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -50,7 +50,7 @@ class ControlFlowGraphBuilder { private val argumentListSplitNodes: Stack = stackOf() private val postponedAnonymousFunctionNodes = - mutableMapOf, Pair, PostponedLambdaExitNode?>>() + mutableMapOf, Pair, PostponedLambdaExitNode?>>() private val postponedLambdaExits: Stack, EdgeKind>>> = stackOf() private val loopConditionEnterNodes: NodeStorage = NodeStorage() @@ -134,16 +134,12 @@ class ControlFlowGraphBuilder { is FirConstructor -> "" else -> throw IllegalArgumentException("Unknown function: ${function.render()}") } - val graph = ControlFlowGraph(function, name, ControlFlowGraph.Kind.Function) - // function is local + val localFunctionNode = runIf(function.symbol.callableId.isLocal && currentGraph.kind.withBody) { - currentGraph.addSubGraph(graph) - createLocalFunctionDeclarationNode(function).also { - addNewSimpleNode(it) - } + createLocalFunctionDeclarationNode(function).also { addNewSimpleNode(it) } } - pushGraph(graph) + pushGraph(ControlFlowGraph(function, name, ControlFlowGraph.Kind.Function)) val enterNode = createFunctionEnterNode(function).also { lastNodes.push(it) @@ -266,10 +262,6 @@ class ControlFlowGraphBuilder { assert(graph.exitNode == exitNode) val (splitNode, postponedExitNode) = postponedAnonymousFunctionNodes.remove(symbol)!! - splitNode.addSubGraph(graph) - // May not be the current graph: `select(run { run { generic() } }, 1)` - splitNode.owner.addSubGraph(graph) - val invocationKind = anonymousFunction.invocationKind if (postponedExitNode == null) { // Postponed exit node was needed so we could create lambda->call edges without having the subgraph ready. If it @@ -411,7 +403,6 @@ class ControlFlowGraphBuilder { var prevInitPartNode: CFGNode<*>? = null for (graph in calledInPlace) { createPartOfClassInitializationNode(graph.declaration as FirControlFlowGraphOwner).also { - currentGraph.addSubGraph(graph) addEdge(node, it, preferredKind = EdgeKind.CfgForward) addEdge(it, graph.enterNode, preferredKind = EdgeKind.CfgForward) node = graph.exitNode @@ -435,10 +426,9 @@ class ControlFlowGraphBuilder { // println(x) for (graph in calledLater) { addEdge(exitNode, graph.enterNode, preferredKind = EdgeKind.CfgForward) - exitNode.addSubGraph(graph) - currentGraph.addSubGraph(graph) } + exitNode.subGraphs = calledLater return popGraph() } @@ -455,9 +445,7 @@ class ControlFlowGraphBuilder { } fun exitLocalClass(klass: FirRegularClass): Pair { - val graph = exitClass(klass).also { - currentGraph.addSubGraph(it) - } + val graph = exitClass(klass) val node = createLocalClassExitNode(klass).also { addNewSimpleNodeIfPossible(it) } @@ -475,9 +463,7 @@ class ControlFlowGraphBuilder { } fun exitAnonymousObject(anonymousObject: FirAnonymousObject): Pair { - val graph = exitClass(anonymousObject).also { - currentGraph.addSubGraph(it) - } + val graph = exitClass(anonymousObject) val enterNode = lastNodes.popOrNull() if (enterNode !is AnonymousObjectEnterNode) { throw AssertionError("anonymous object exit should be preceded by anonymous object enter, but got $enterNode") @@ -535,12 +521,9 @@ class ControlFlowGraphBuilder { popAndAddEdge(exitNode) val graph = popGraph() require(exitNode == graph.exitNode) - val outerEnterNode = lastNode as EnterValueParameterNode val outerExitNode = createExitValueParameterNode(valueParameter) addNewSimpleNode(outerExitNode) addEdge(exitNode, outerExitNode, propagateDeadness = false) - outerEnterNode.addSubGraph(graph) - currentGraph.addSubGraph(graph) return Triple(exitNode, outerExitNode, graph) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt index ea626266768..5be8abfb856 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphRenderer.kt @@ -154,7 +154,7 @@ class FirControlFlowGraphRenderVisitor( private fun initializeNodes(graph: ControlFlowGraph) { if (graph in allGraphs) return graph.collectNodes() - if (graph.owner == null) { + if (!graph.isSubGraph) { topLevelGraphs += graph } allGraphs += graph diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt index 0e20bfe23f6..3ea62150e05 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt @@ -142,21 +142,12 @@ interface UnionNodeMarker // ----------------------------------- EnterNode for declaration with CFG ----------------------------------- sealed class CFGNodeWithSubgraphs(owner: ControlFlowGraph, level: Int, id: Int) : CFGNode(owner, level, id) { - private val _subGraphs = mutableListOf() - - fun addSubGraph(graph: ControlFlowGraph){ - _subGraphs += graph - } - - open val subGraphs: List - get() = _subGraphs + abstract val subGraphs: List } sealed class CFGNodeWithCfgOwner(owner: ControlFlowGraph, level: Int, id: Int) : CFGNodeWithSubgraphs(owner, level, id) { - override val subGraphs: List by lazy { - fir.controlFlowGraphReference?.controlFlowGraph?.run(::addSubGraph) - super.subGraphs - } + final override val subGraphs: List + get() = listOfNotNull(fir.controlFlowGraphReference?.controlFlowGraph) } // ----------------------------------- Named function ----------------------------------- @@ -222,6 +213,10 @@ class ExitValueParameterNode(owner: ControlFlowGraph, override val fir: FirValue class SplitPostponedLambdasNode(owner: ControlFlowGraph, override val fir: FirStatement, val lambdas: List, level: Int, id: Int) : CFGNodeWithSubgraphs(owner, level, id) { + + override val subGraphs: List + get() = lambdas.mapNotNull { it.controlFlowGraphReference?.controlFlowGraph } + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { return visitor.visitSplitPostponedLambdasNode(this, data) } @@ -240,6 +235,9 @@ class MergePostponedLambdaExitsNode(owner: ControlFlowGraph, override val fir: F } class AnonymousFunctionExpressionNode(owner: ControlFlowGraph, override val fir: FirAnonymousFunctionExpression, level: Int, id: Int) : CFGNodeWithSubgraphs(owner, level, id) { + override val subGraphs: List + get() = listOfNotNull(fir.anonymousFunction.controlFlowGraphReference?.controlFlowGraph) + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { return visitor.visitAnonymousFunctionExpressionNode(this, data) } @@ -266,6 +264,8 @@ class ClassExitNode(owner: ControlFlowGraph, override val fir: FirClass, level: owner.exitNode = this } + lateinit override var subGraphs: List + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { return visitor.visitClassExitNode(this, data) } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index ce425e38227..fab95f9f7fd 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -26,14 +26,14 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k @set:CfgInternals lateinit var exitNode: CFGNode<*> - var owner: ControlFlowGraph? = null - private set + val isSubGraph: Boolean + get() = enterNode.previousNodes.isNotEmpty() var state: State = State.Building private set - private val _subGraphs: MutableList = mutableListOf() - val subGraphs: List get() = _subGraphs + val subGraphs: List + get() = _nodes.flatMap { (it as? CFGNodeWithSubgraphs<*>)?.subGraphs ?: emptyList() } @CfgInternals fun complete() { @@ -50,15 +50,6 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k _nodes.addAll(sortedNodes) } - @CfgInternals - fun addSubGraph(graph: ControlFlowGraph) { - assert(graph.owner == null) { - "SubGraph already has owner" - } - graph.owner = this - _subGraphs += graph - } - private fun assertState(state: State) { assert(this.state == state) { "This action can not be performed at $this state" @@ -171,34 +162,16 @@ private fun ControlFlowGraph.orderNodes(): LinkedHashSet> { continue } if (!visitedNodes.add(node)) continue - val followingNodes = node.followingNodes - for (followingNode in followingNodes) { + // NOTE: this intentionally does not walk through subgraphs. If the only path from A to B + // is through a subgraph, add a dead edge between them to enforce ordering. + for (followingNode in node.followingNodes) { if (followingNode.owner == this) { if (followingNode !in visitedNodes) { stack.addFirst(followingNode) } - } else { - walkThrowSubGraphs(followingNode.owner, visitedNodes, stack) } } } return visitedNodes } - -private fun ControlFlowGraph.walkThrowSubGraphs( - otherGraph: ControlFlowGraph, - visitedNodes: Set>, - stack: ArrayDeque> -) { - if (otherGraph.owner != this) return - for (otherNode in otherGraph.exitNode.followingNodes) { - if (otherNode.owner == this) { - if (otherNode !in visitedNodes) { - stack.addFirst(otherNode) - } - } else if (otherNode.owner != otherGraph) { - walkThrowSubGraphs(otherNode.owner, visitedNodes, stack) - } - } -} diff --git a/compiler/testData/codegen/box/smartCasts/kt44814.dot b/compiler/testData/codegen/box/smartCasts/kt44814.dot index e00a16f7f7d..f283d5cf6dc 100644 --- a/compiler/testData/codegen/box/smartCasts/kt44814.dot +++ b/compiler/testData/codegen/box/smartCasts/kt44814.dot @@ -235,7 +235,7 @@ digraph kt44814_kt { 71 -> {75} [color=green]; 50 -> {51}; 51 -> {52 55}; - 51 -> {55 55} [style=dashed]; + 51 -> {55} [style=dashed]; 52 -> {53}; 53 -> {54}; 55 -> {56}; @@ -576,20 +576,20 @@ digraph kt44814_kt { 193 [label="Postponed enter to lambda [8]"]; subgraph cluster_62 { color=blue - 240 [label="Enter function anonymousFunction [9]" style="filled" fillcolor=red]; + 234 [label="Enter function anonymousFunction [9]" style="filled" fillcolor=red]; subgraph cluster_63 { color=blue - 241 [label="Enter block [9]"]; - 242 [label="Access variable R|/it| [9]"]; - 243 [label="Enter safe call [9]"]; - 244 [label="Access variable R|/LighterASTNode.tokenType| [9]"]; - 245 [label="Exit safe call [9]"]; - 246 [label="Access qualifier /TokenType [9]"]; - 247 [label="Access variable R|/TokenType.Companion.MODIFIER_LIST| [9]"]; - 248 [label="Equality operator == [9]"]; - 249 [label="Exit block [9]"]; + 235 [label="Enter block [9]"]; + 236 [label="Access variable R|/it| [9]"]; + 237 [label="Enter safe call [9]"]; + 238 [label="Access variable R|/LighterASTNode.tokenType| [9]"]; + 239 [label="Exit safe call [9]"]; + 240 [label="Access qualifier /TokenType [9]"]; + 241 [label="Access variable R|/TokenType.Companion.MODIFIER_LIST| [9]"]; + 242 [label="Equality operator == [9]"]; + 243 [label="Exit block [9]"]; } - 250 [label="Exit function anonymousFunction [9]" style="filled" fillcolor=red]; + 244 [label="Exit function anonymousFunction [9]" style="filled" fillcolor=red]; } 194 [label="Postponed exit from lambda [8]"]; 195 [label="Function call: this@R|/FirModifierList.Companion.getModifierList|.R|/FirLightSourceElement.lighterASTNode|.R|/LighterASTNode.getChildren|(...).R|kotlin/collections/find|(...) [7]" style="filled" fillcolor=yellow]; @@ -619,15 +619,15 @@ digraph kt44814_kt { 216 [label="Postponed enter to lambda [7]"]; subgraph cluster_65 { color=blue - 234 [label="Enter function anonymousFunction [8]" style="filled" fillcolor=red]; + 245 [label="Enter function anonymousFunction [8]" style="filled" fillcolor=red]; subgraph cluster_66 { color=blue - 235 [label="Enter block [8]"]; - 236 [label="Access variable R|/it| [9]"]; - 237 [label="Function call: R|/FirModifierList.FirPsiModifierList.FirPsiModifierList|(...) [8]" style="filled" fillcolor=yellow]; - 238 [label="Exit block [8]"]; + 246 [label="Enter block [8]"]; + 247 [label="Access variable R|/it| [9]"]; + 248 [label="Function call: R|/FirModifierList.FirPsiModifierList.FirPsiModifierList|(...) [8]" style="filled" fillcolor=yellow]; + 249 [label="Exit block [8]"]; } - 239 [label="Exit function anonymousFunction [8]" style="filled" fillcolor=red]; + 250 [label="Exit function anonymousFunction [8]" style="filled" fillcolor=red]; } 217 [label="Postponed exit from lambda [7]"]; 218 [label="Function call: $subj$.R|kotlin/let|(...) [6]" style="filled" fillcolor=yellow]; @@ -792,8 +792,8 @@ digraph kt44814_kt { 190 -> {191}; 191 -> {192}; 192 -> {193}; - 193 -> {194 195 240}; - 193 -> {240} [style=dashed]; + 193 -> {194 195 234}; + 193 -> {234} [style=dashed]; 194 -> {195}; 194 -> {193} [color=green style=dashed]; 195 -> {196}; @@ -818,9 +818,9 @@ digraph kt44814_kt { 213 -> {214}; 214 -> {215 219}; 215 -> {216}; - 216 -> {218 234}; + 216 -> {218 245}; 216 -> {217} [style=dotted]; - 216 -> {234} [style=dashed]; + 216 -> {245} [style=dashed]; 217 -> {218} [color=green]; 217 -> {223} [color=red]; 218 -> {220}; @@ -841,21 +841,21 @@ digraph kt44814_kt { 232 -> {233} [style=dotted]; 234 -> {235}; 235 -> {236}; - 236 -> {237}; + 236 -> {237 239}; 237 -> {238}; 238 -> {239}; - 239 -> {217}; + 239 -> {240}; 240 -> {241}; 241 -> {242}; - 242 -> {243 245}; + 242 -> {243}; 243 -> {244}; - 244 -> {245}; + 244 -> {194}; 245 -> {246}; 246 -> {247}; 247 -> {248}; 248 -> {249}; 249 -> {250}; - 250 -> {194}; + 250 -> {217}; 251 -> {252}; 252 -> {253}; 253 -> {254};