From 163c5d699fdff2058ff07724b3c39115df16cd59 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 28 Aug 2019 12:41:07 +0300 Subject: [PATCH] [FIR] Pass flow to right operand of && expression --- .../resolve/dfa/FirDataFlowAnalyzerImpl.kt | 4 +- .../fir/resolve/dfa/cfg/ControlFlowGraph.kt | 4 +- .../dfa/cfg/ControlFlowGraphBuilder.kt | 10 +- .../dfa/cfg/ControlFlowGraphNodeBuilder.kt | 3 + .../dfa/cfg/ControlFlowGraphRenderer.kt | 1 + .../testData/resolve/cfg/binaryOperations.dot | 182 +++---- .../cfg/booleanOperatorsWithConsts.dot | 235 +++++---- .../fir/resolve/testData/resolve/cfg/when.dot | 46 +- .../resolve/smartcasts/booleanOperators.dot | 484 ++++++++++-------- .../resolve/smartcasts/booleanOperators.kt | 8 + .../resolve/smartcasts/booleanOperators.txt | 12 + .../testData/resolve/smartcasts/casts.dot | 282 +++++----- 12 files changed, 694 insertions(+), 577 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt index 4eed06bdb1d..8871ec40f44 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt @@ -488,7 +488,9 @@ class FirDataFlowAnalyzerImpl(transformer: FirBodyResolveTransformer) : FirDataF } override fun exitLeftBinaryAndArgument(binaryLogicExpression: FirBinaryLogicExpression) { - graphBuilder.exitLeftBinaryAndArgument(binaryLogicExpression) + val node = graphBuilder.exitLeftBinaryAndArgument(binaryLogicExpression).passFlow(false) + val leftOperandVariable = getVariable(node.previousNodes.first().fir) + node.flow = logicSystem.approveFactsInsideFlow(leftOperandVariable eq True, node.flow).also { it.freeze() } } override fun exitBinaryAnd(binaryLogicExpression: FirBinaryLogicExpression) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index 887a0e6f78c..ea9a41c8e1e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -99,10 +99,10 @@ abstract class AbstractBinaryExitNode(owner: ControlFlowGraph, l } class BinaryAndEnterNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : CFGNode(owner, level) +class BinaryAndExitLeftOperandNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : CFGNode(owner, level) class BinaryAndExitNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : AbstractBinaryExitNode(owner, level) -class BinaryOrEnterNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : CFGNode(owner, level) -// Exit left node pass after left argument in case if that argument is `false` +class BinaryOrEnterNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : CFGNode(owner, level) class BinaryOrExitLeftOperandNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : CFGNode(owner, level) class BinaryOrExitNode(owner: ControlFlowGraph, override val fir: FirBinaryLogicExpression, level: Int) : AbstractBinaryExitNode(owner, level) 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 c7fef99fdc6..de576423233 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 @@ -303,9 +303,15 @@ class ControlFlowGraphBuilder : ControlFlowGraphNodeBuilder() { return createBinaryAndEnterNode(binaryLogicExpression).also { addNewSimpleNode(it) }.also { levelCounter++ } } - fun exitLeftBinaryAndArgument(binaryLogicExpression: FirBinaryLogicExpression) { + fun exitLeftBinaryAndArgument(binaryLogicExpression: FirBinaryLogicExpression): BinaryAndExitLeftOperandNode { assert(binaryLogicExpression.kind == FirBinaryLogicExpression.OperationKind.AND) - addEdge(lastNode, binaryAndExitNodes.top(), propagateDeadness = false, isDead = lastNode.booleanConstValue == true) + val lastNode = lastNodes.pop() + val leftBooleanConstValue = lastNode.booleanConstValue + addEdge(lastNode, binaryAndExitNodes.top(), propagateDeadness = false, isDead = leftBooleanConstValue == true) + return createBinaryAndExitLeftOperandNode(binaryLogicExpression).also { + addEdge(lastNode, it, isDead = leftBooleanConstValue == false) + lastNodes.push(it) + } } fun exitBinaryAnd(binaryLogicExpression: FirBinaryLogicExpression): BinaryAndExitNode { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt index e8a53ebd289..f87ca110b11 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt @@ -158,4 +158,7 @@ abstract class ControlFlowGraphNodeBuilder { protected fun createTryExpressionExitNode(fir: FirTryExpression): TryExpressionExitNode = TryExpressionExitNode(graph, fir, levelCounter) + protected fun createBinaryAndExitLeftOperandNode(fir: FirBinaryLogicExpression): BinaryAndExitLeftOperandNode = + BinaryAndExitLeftOperandNode(graph, fir, levelCounter) + } \ No newline at end of file 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 fa1eb141714..20b7afbc253 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 @@ -133,6 +133,7 @@ fun CFGNode<*>.render(): String = is TryExpressionExitNode -> "Try expression exit" is BinaryAndEnterNode -> "Enter &&" + is BinaryAndExitLeftOperandNode -> "Exit left part of &&" is BinaryAndExitNode -> "Exit &&" is BinaryOrEnterNode -> "Enter ||" is BinaryOrExitLeftOperandNode -> "Exit left part of ||" diff --git a/compiler/fir/resolve/testData/resolve/cfg/binaryOperations.dot b/compiler/fir/resolve/testData/resolve/cfg/binaryOperations.dot index e075ccfc50c..1c8c05c2291 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/binaryOperations.dot +++ b/compiler/fir/resolve/testData/resolve/cfg/binaryOperations.dot @@ -55,148 +55,154 @@ subgraph test_2 { 25 [shape=box label="Enter when branch condition "]; 26 [shape=box label="Enter &&"]; 27 [shape=box label="Access variable R|/b1|"]; - 28 [shape=box label="Access variable R|/b2|"]; - 29 [shape=box label="Exit &&"]; - 30 [shape=box label="Exit when branch condition"]; - 31 [shape=box label="Enter block"]; - 32 [shape=box label="Const: Int(1)"]; - 33 [shape=box label="Exit block"]; - 34 [shape=box label="Exit when branch result"]; - 35 [shape=box label="Enter when branch condition else"]; - 36 [shape=box label="Exit when branch condition"]; - 37 [shape=box label="Enter block"]; - 38 [shape=box label="Exit block"]; - 39 [shape=box label="Exit when branch result"]; - 40 [shape=box label="Exit when"]; - 41 [shape=box label="Exit block"]; - 42 [shape=box label="Exit function test_2"]; + 28 [shape=box label="Exit left part of &&"]; + 29 [shape=box label="Access variable R|/b2|"]; + 30 [shape=box label="Exit &&"]; + 31 [shape=box label="Exit when branch condition"]; + 32 [shape=box label="Enter block"]; + 33 [shape=box label="Const: Int(1)"]; + 34 [shape=box label="Exit block"]; + 35 [shape=box label="Exit when branch result"]; + 36 [shape=box label="Enter when branch condition else"]; + 37 [shape=box label="Exit when branch condition"]; + 38 [shape=box label="Enter block"]; + 39 [shape=box label="Exit block"]; + 40 [shape=box label="Exit when branch result"]; + 41 [shape=box label="Exit when"]; + 42 [shape=box label="Exit block"]; + 43 [shape=box label="Exit function test_2"]; 22 -> {23}; 23 -> {24}; 24 -> {25}; 25 -> {26}; 26 -> {27}; - 27 -> {29 28}; + 27 -> {30 28}; 28 -> {29}; 29 -> {30}; - 30 -> {31 35}; - 31 -> {32}; + 30 -> {31}; + 31 -> {32 36}; 32 -> {33}; 33 -> {34}; - 34 -> {40}; - 35 -> {36}; + 34 -> {35}; + 35 -> {41}; 36 -> {37}; 37 -> {38}; 38 -> {39}; 39 -> {40}; 40 -> {41}; 41 -> {42}; + 42 -> {43}; } subgraph test_3 { - 43 [shape=box label="Enter function test_3"]; - 44 [shape=box label="Enter block"]; - 45 [shape=box label="Enter when"]; - 46 [shape=box label="Enter when branch condition "]; - 47 [shape=box label="Enter ||"]; - 48 [shape=box label="Enter &&"]; - 49 [shape=box label="Access variable R|/b1|"]; - 50 [shape=box label="Access variable R|/b2|"]; - 51 [shape=box label="Exit &&"]; - 52 [shape=box label="Exit left part of ||"]; - 53 [shape=box label="Access variable R|/b3|"]; - 54 [shape=box label="Exit ||"]; - 55 [shape=box label="Exit when branch condition"]; - 56 [shape=box label="Enter block"]; - 57 [shape=box label="Const: Int(1)"]; - 58 [shape=box label="Exit block"]; - 59 [shape=box label="Exit when branch result"]; - 60 [shape=box label="Enter when branch condition else"]; - 61 [shape=box label="Exit when branch condition"]; - 62 [shape=box label="Enter block"]; - 63 [shape=box label="Exit block"]; - 64 [shape=box label="Exit when branch result"]; - 65 [shape=box label="Exit when"]; - 66 [shape=box label="Exit block"]; - 67 [shape=box label="Exit function test_3"]; + 44 [shape=box label="Enter function test_3"]; + 45 [shape=box label="Enter block"]; + 46 [shape=box label="Enter when"]; + 47 [shape=box label="Enter when branch condition "]; + 48 [shape=box label="Enter ||"]; + 49 [shape=box label="Enter &&"]; + 50 [shape=box label="Access variable R|/b1|"]; + 51 [shape=box label="Exit left part of &&"]; + 52 [shape=box label="Access variable R|/b2|"]; + 53 [shape=box label="Exit &&"]; + 54 [shape=box label="Exit left part of ||"]; + 55 [shape=box label="Access variable R|/b3|"]; + 56 [shape=box label="Exit ||"]; + 57 [shape=box label="Exit when branch condition"]; + 58 [shape=box label="Enter block"]; + 59 [shape=box label="Const: Int(1)"]; + 60 [shape=box label="Exit block"]; + 61 [shape=box label="Exit when branch result"]; + 62 [shape=box label="Enter when branch condition else"]; + 63 [shape=box label="Exit when branch condition"]; + 64 [shape=box label="Enter block"]; + 65 [shape=box label="Exit block"]; + 66 [shape=box label="Exit when branch result"]; + 67 [shape=box label="Exit when"]; + 68 [shape=box label="Exit block"]; + 69 [shape=box label="Exit function test_3"]; - 43 -> {44}; 44 -> {45}; 45 -> {46}; 46 -> {47}; 47 -> {48}; 48 -> {49}; - 49 -> {51 50}; - 50 -> {51}; - 51 -> {54 52}; + 49 -> {50}; + 50 -> {53 51}; + 51 -> {52}; 52 -> {53}; - 53 -> {54}; + 53 -> {56 54}; 54 -> {55}; - 55 -> {56 60}; + 55 -> {56}; 56 -> {57}; - 57 -> {58}; + 57 -> {58 62}; 58 -> {59}; - 59 -> {65}; + 59 -> {60}; 60 -> {61}; - 61 -> {62}; + 61 -> {67}; 62 -> {63}; 63 -> {64}; 64 -> {65}; 65 -> {66}; 66 -> {67}; + 67 -> {68}; + 68 -> {69}; } subgraph test_4 { - 68 [shape=box label="Enter function test_4"]; - 69 [shape=box label="Enter block"]; - 70 [shape=box label="Enter when"]; - 71 [shape=box label="Enter when branch condition "]; - 72 [shape=box label="Enter ||"]; - 73 [shape=box label="Access variable R|/b1|"]; - 74 [shape=box label="Exit left part of ||"]; - 75 [shape=box label="Enter &&"]; - 76 [shape=box label="Access variable R|/b2|"]; - 77 [shape=box label="Access variable R|/b3|"]; - 78 [shape=box label="Exit &&"]; - 79 [shape=box label="Exit ||"]; - 80 [shape=box label="Exit when branch condition"]; - 81 [shape=box label="Enter block"]; - 82 [shape=box label="Const: Int(1)"]; - 83 [shape=box label="Exit block"]; - 84 [shape=box label="Exit when branch result"]; - 85 [shape=box label="Enter when branch condition else"]; - 86 [shape=box label="Exit when branch condition"]; - 87 [shape=box label="Enter block"]; - 88 [shape=box label="Exit block"]; - 89 [shape=box label="Exit when branch result"]; - 90 [shape=box label="Exit when"]; + 70 [shape=box label="Enter function test_4"]; + 71 [shape=box label="Enter block"]; + 72 [shape=box label="Enter when"]; + 73 [shape=box label="Enter when branch condition "]; + 74 [shape=box label="Enter ||"]; + 75 [shape=box label="Access variable R|/b1|"]; + 76 [shape=box label="Exit left part of ||"]; + 77 [shape=box label="Enter &&"]; + 78 [shape=box label="Access variable R|/b2|"]; + 79 [shape=box label="Exit left part of &&"]; + 80 [shape=box label="Access variable R|/b3|"]; + 81 [shape=box label="Exit &&"]; + 82 [shape=box label="Exit ||"]; + 83 [shape=box label="Exit when branch condition"]; + 84 [shape=box label="Enter block"]; + 85 [shape=box label="Const: Int(1)"]; + 86 [shape=box label="Exit block"]; + 87 [shape=box label="Exit when branch result"]; + 88 [shape=box label="Enter when branch condition else"]; + 89 [shape=box label="Exit when branch condition"]; + 90 [shape=box label="Enter block"]; 91 [shape=box label="Exit block"]; - 92 [shape=box label="Exit function test_4"]; + 92 [shape=box label="Exit when branch result"]; + 93 [shape=box label="Exit when"]; + 94 [shape=box label="Exit block"]; + 95 [shape=box label="Exit function test_4"]; - 68 -> {69}; - 69 -> {70}; 70 -> {71}; 71 -> {72}; 72 -> {73}; - 73 -> {79 74}; + 73 -> {74}; 74 -> {75}; - 75 -> {76}; - 76 -> {78 77}; + 75 -> {82 76}; + 76 -> {77}; 77 -> {78}; - 78 -> {79}; + 78 -> {81 79}; 79 -> {80}; - 80 -> {81 85}; + 80 -> {81}; 81 -> {82}; 82 -> {83}; - 83 -> {84}; - 84 -> {90}; + 83 -> {84 88}; + 84 -> {85}; 85 -> {86}; 86 -> {87}; - 87 -> {88}; + 87 -> {93}; 88 -> {89}; 89 -> {90}; 90 -> {91}; 91 -> {92}; + 92 -> {93}; + 93 -> {94}; + 94 -> {95}; } } diff --git a/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot index d59ed88cc37..ffff5409948 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot +++ b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot @@ -202,182 +202,193 @@ subgraph test_5 { 93 [shape=box label="Enter when branch condition "]; 94 [shape=box label="Enter &&"]; 95 [shape=box label="Access variable R|/b|"]; - 96 [shape=box label="Const: Boolean(false)"]; - 97 [shape=box label="Exit &&"]; - 98 [shape=box label="Exit when branch condition"]; - 99 [shape=box label="Enter block"]; - 100 [shape=box label="Const: Int(1)"]; - 101 [shape=box label="Exit block"]; - 102 [shape=box label="Exit when branch result"]; - 103 [shape=box label="Enter when branch condition else"]; - 104 [shape=box label="Exit when branch condition"]; - 105 [shape=box label="Enter block"]; - 106 [shape=box label="Exit block"]; - 107 [shape=box label="Exit when branch result"]; - 108 [shape=box label="Exit when"]; - 109 [shape=box label="Exit block"]; - 110 [shape=box label="Exit function test_5"]; + 96 [shape=box label="Exit left part of &&"]; + 97 [shape=box label="Const: Boolean(false)"]; + 98 [shape=box label="Exit &&"]; + 99 [shape=box label="Exit when branch condition"]; + 100 [shape=box label="Enter block"]; + 101 [shape=box label="Const: Int(1)"]; + 102 [shape=box label="Exit block"]; + 103 [shape=box label="Exit when branch result"]; + 104 [shape=box label="Enter when branch condition else"]; + 105 [shape=box label="Exit when branch condition"]; + 106 [shape=box label="Enter block"]; + 107 [shape=box label="Exit block"]; + 108 [shape=box label="Exit when branch result"]; + 109 [shape=box label="Exit when"]; + 110 [shape=box label="Exit block"]; + 111 [shape=box label="Exit function test_5"]; 90 -> {91}; 91 -> {92}; 92 -> {93}; 93 -> {94}; 94 -> {95}; - 95 -> {97 96}; + 95 -> {98 96}; 96 -> {97}; 97 -> {98}; - 98 -> {99 103}; - 99 -> {100}; + 98 -> {99}; + 99 -> {100 104}; 100 -> {101}; 101 -> {102}; - 102 -> {108}; - 103 -> {104}; + 102 -> {103}; + 103 -> {109}; 104 -> {105}; 105 -> {106}; 106 -> {107}; 107 -> {108}; 108 -> {109}; 109 -> {110}; + 110 -> {111}; } subgraph test_6 { - 111 [shape=box label="Enter function test_6"]; - 112 [shape=box label="Enter block"]; - 113 [shape=box label="Enter when"]; - 114 [shape=box label="Enter when branch condition "]; - 115 [shape=box label="Enter &&"]; - 116 [shape=box label="Const: Boolean(false)"]; - 117 [shape=box label="Access variable R|/b|"]; + 112 [shape=box label="Enter function test_6"]; + 113 [shape=box label="Enter block"]; + 114 [shape=box label="Enter when"]; + 115 [shape=box label="Enter when branch condition "]; + 116 [shape=box label="Enter &&"]; + 117 [shape=box label="Const: Boolean(false)"]; 118 [shape=box label="Stub[DEAD]"]; - 119 [shape=box label="Exit &&"]; - 120 [shape=box label="Exit when branch condition"]; - 121 [shape=box label="Enter block"]; - 122 [shape=box label="Const: Int(1)"]; - 123 [shape=box label="Exit block"]; - 124 [shape=box label="Exit when branch result"]; - 125 [shape=box label="Enter when branch condition else"]; - 126 [shape=box label="Exit when branch condition"]; - 127 [shape=box label="Enter block"]; - 128 [shape=box label="Exit block"]; - 129 [shape=box label="Exit when branch result"]; - 130 [shape=box label="Exit when"]; + 119 [shape=box label="Exit left part of &&[DEAD]"]; + 120 [shape=box label="Access variable R|/b|[DEAD]"]; + 121 [shape=box label="Stub[DEAD]"]; + 122 [shape=box label="Exit &&"]; + 123 [shape=box label="Exit when branch condition"]; + 124 [shape=box label="Enter block"]; + 125 [shape=box label="Const: Int(1)"]; + 126 [shape=box label="Exit block"]; + 127 [shape=box label="Exit when branch result"]; + 128 [shape=box label="Enter when branch condition else"]; + 129 [shape=box label="Exit when branch condition"]; + 130 [shape=box label="Enter block"]; 131 [shape=box label="Exit block"]; - 132 [shape=box label="Exit function test_6"]; + 132 [shape=box label="Exit when branch result"]; + 133 [shape=box label="Exit when"]; + 134 [shape=box label="Exit block"]; + 135 [shape=box label="Exit function test_6"]; - 111 -> {112}; 112 -> {113}; 113 -> {114}; 114 -> {115}; 115 -> {116}; - 116 -> {119 117}; + 116 -> {117}; + 117 -> {122}; 117 -> {118} [style=dotted]; 118 -> {119} [style=dotted]; - 119 -> {120}; - 120 -> {121 125}; - 121 -> {122}; + 119 -> {120} [style=dotted]; + 120 -> {121} [style=dotted]; + 121 -> {122} [style=dotted]; 122 -> {123}; - 123 -> {124}; - 124 -> {130}; + 123 -> {124 128}; + 124 -> {125}; 125 -> {126}; 126 -> {127}; - 127 -> {128}; + 127 -> {133}; 128 -> {129}; 129 -> {130}; 130 -> {131}; 131 -> {132}; + 132 -> {133}; + 133 -> {134}; + 134 -> {135}; } subgraph test_7 { - 133 [shape=box label="Enter function test_7"]; - 134 [shape=box label="Enter block"]; - 135 [shape=box label="Enter when"]; - 136 [shape=box label="Enter when branch condition "]; - 137 [shape=box label="Enter &&"]; - 138 [shape=box label="Access variable R|/b|"]; - 139 [shape=box label="Const: Boolean(true)"]; - 140 [shape=box label="Exit &&"]; - 141 [shape=box label="Exit when branch condition"]; - 142 [shape=box label="Enter block"]; - 143 [shape=box label="Const: Int(1)"]; - 144 [shape=box label="Exit block"]; - 145 [shape=box label="Exit when branch result"]; - 146 [shape=box label="Enter when branch condition else"]; - 147 [shape=box label="Exit when branch condition"]; - 148 [shape=box label="Enter block"]; - 149 [shape=box label="Exit block"]; - 150 [shape=box label="Exit when branch result"]; - 151 [shape=box label="Exit when"]; - 152 [shape=box label="Exit block"]; - 153 [shape=box label="Exit function test_7"]; + 136 [shape=box label="Enter function test_7"]; + 137 [shape=box label="Enter block"]; + 138 [shape=box label="Enter when"]; + 139 [shape=box label="Enter when branch condition "]; + 140 [shape=box label="Enter &&"]; + 141 [shape=box label="Access variable R|/b|"]; + 142 [shape=box label="Exit left part of &&"]; + 143 [shape=box label="Const: Boolean(true)"]; + 144 [shape=box label="Exit &&"]; + 145 [shape=box label="Exit when branch condition"]; + 146 [shape=box label="Enter block"]; + 147 [shape=box label="Const: Int(1)"]; + 148 [shape=box label="Exit block"]; + 149 [shape=box label="Exit when branch result"]; + 150 [shape=box label="Enter when branch condition else"]; + 151 [shape=box label="Exit when branch condition"]; + 152 [shape=box label="Enter block"]; + 153 [shape=box label="Exit block"]; + 154 [shape=box label="Exit when branch result"]; + 155 [shape=box label="Exit when"]; + 156 [shape=box label="Exit block"]; + 157 [shape=box label="Exit function test_7"]; - 133 -> {134}; - 134 -> {135}; - 135 -> {136}; 136 -> {137}; 137 -> {138}; - 138 -> {140 139}; + 138 -> {139}; 139 -> {140}; 140 -> {141}; - 141 -> {142 146}; + 141 -> {144 142}; 142 -> {143}; 143 -> {144}; 144 -> {145}; - 145 -> {151}; + 145 -> {146 150}; 146 -> {147}; 147 -> {148}; 148 -> {149}; - 149 -> {150}; + 149 -> {155}; 150 -> {151}; 151 -> {152}; 152 -> {153}; -} - -subgraph test_8 { - 154 [shape=box label="Enter function test_8"]; - 155 [shape=box label="Enter block"]; - 156 [shape=box label="Enter when"]; - 157 [shape=box label="Enter when branch condition "]; - 158 [shape=box label="Enter &&"]; - 159 [shape=box label="Const: Boolean(true)"]; - 160 [shape=box label="Access variable R|/b|"]; - 161 [shape=box label="Stub[DEAD]"]; - 162 [shape=box label="Exit &&"]; - 163 [shape=box label="Exit when branch condition"]; - 164 [shape=box label="Enter block"]; - 165 [shape=box label="Const: Int(1)"]; - 166 [shape=box label="Exit block"]; - 167 [shape=box label="Exit when branch result"]; - 168 [shape=box label="Enter when branch condition else"]; - 169 [shape=box label="Exit when branch condition"]; - 170 [shape=box label="Enter block"]; - 171 [shape=box label="Exit block"]; - 172 [shape=box label="Exit when branch result"]; - 173 [shape=box label="Exit when"]; - 174 [shape=box label="Exit block"]; - 175 [shape=box label="Exit function test_8"]; - + 153 -> {154}; 154 -> {155}; 155 -> {156}; 156 -> {157}; - 157 -> {158}; +} + +subgraph test_8 { + 158 [shape=box label="Enter function test_8"]; + 159 [shape=box label="Enter block"]; + 160 [shape=box label="Enter when"]; + 161 [shape=box label="Enter when branch condition "]; + 162 [shape=box label="Enter &&"]; + 163 [shape=box label="Const: Boolean(true)"]; + 164 [shape=box label="Exit left part of &&"]; + 165 [shape=box label="Access variable R|/b|"]; + 166 [shape=box label="Stub[DEAD]"]; + 167 [shape=box label="Exit &&"]; + 168 [shape=box label="Exit when branch condition"]; + 169 [shape=box label="Enter block"]; + 170 [shape=box label="Const: Int(1)"]; + 171 [shape=box label="Exit block"]; + 172 [shape=box label="Exit when branch result"]; + 173 [shape=box label="Enter when branch condition else"]; + 174 [shape=box label="Exit when branch condition"]; + 175 [shape=box label="Enter block"]; + 176 [shape=box label="Exit block"]; + 177 [shape=box label="Exit when branch result"]; + 178 [shape=box label="Exit when"]; + 179 [shape=box label="Exit block"]; + 180 [shape=box label="Exit function test_8"]; + 158 -> {159}; 159 -> {160}; - 159 -> {161} [style=dotted]; - 160 -> {162}; - 161 -> {162} [style=dotted]; + 160 -> {161}; + 161 -> {162}; 162 -> {163}; - 163 -> {164 168}; + 163 -> {164}; + 163 -> {166} [style=dotted]; 164 -> {165}; - 165 -> {166}; - 166 -> {167}; - 167 -> {173}; - 168 -> {169}; + 165 -> {167}; + 166 -> {167} [style=dotted]; + 167 -> {168}; + 168 -> {169 173}; 169 -> {170}; 170 -> {171}; 171 -> {172}; - 172 -> {173}; + 172 -> {178}; 173 -> {174}; 174 -> {175}; + 175 -> {176}; + 176 -> {177}; + 177 -> {178}; + 178 -> {179}; + 179 -> {180}; } } diff --git a/compiler/fir/resolve/testData/resolve/cfg/when.dot b/compiler/fir/resolve/testData/resolve/cfg/when.dot index bb1d94798f3..af095017b70 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/when.dot +++ b/compiler/fir/resolve/testData/resolve/cfg/when.dot @@ -103,23 +103,24 @@ subgraph test_2 { 49 [shape=box label="Enter &&"]; 50 [shape=box label="Access variable R|/x|"]; 51 [shape=box label="Type operator: x is A"]; - 52 [shape=box label="Access variable R|/x|"]; - 53 [shape=box label="Type operator: x is B"]; - 54 [shape=box label="Exit &&"]; - 55 [shape=box label="Exit when branch condition"]; - 56 [shape=box label="Enter block"]; - 57 [shape=box label="Access variable R|/x|"]; - 58 [shape=box label="Type operator: x is A"]; - 59 [shape=box label="Exit block"]; - 60 [shape=box label="Exit when branch result"]; - 61 [shape=box label="Enter when branch condition else"]; - 62 [shape=box label="Exit when branch condition"]; - 63 [shape=box label="Enter block"]; - 64 [shape=box label="Exit block"]; - 65 [shape=box label="Exit when branch result"]; - 66 [shape=box label="Exit when"]; - 67 [shape=box label="Exit block"]; - 68 [shape=box label="Exit function test_2"]; + 52 [shape=box label="Exit left part of &&"]; + 53 [shape=box label="Access variable R|/x|"]; + 54 [shape=box label="Type operator: x is B"]; + 55 [shape=box label="Exit &&"]; + 56 [shape=box label="Exit when branch condition"]; + 57 [shape=box label="Enter block"]; + 58 [shape=box label="Access variable R|/x|"]; + 59 [shape=box label="Type operator: x is A"]; + 60 [shape=box label="Exit block"]; + 61 [shape=box label="Exit when branch result"]; + 62 [shape=box label="Enter when branch condition else"]; + 63 [shape=box label="Exit when branch condition"]; + 64 [shape=box label="Enter block"]; + 65 [shape=box label="Exit block"]; + 66 [shape=box label="Exit when branch result"]; + 67 [shape=box label="Exit when"]; + 68 [shape=box label="Exit block"]; + 69 [shape=box label="Exit function test_2"]; 45 -> {46}; 46 -> {47}; @@ -127,23 +128,24 @@ subgraph test_2 { 48 -> {49}; 49 -> {50}; 50 -> {51}; - 51 -> {54 52}; + 51 -> {55 52}; 52 -> {53}; 53 -> {54}; 54 -> {55}; - 55 -> {56 61}; - 56 -> {57}; + 55 -> {56}; + 56 -> {57 62}; 57 -> {58}; 58 -> {59}; 59 -> {60}; - 60 -> {66}; - 61 -> {62}; + 60 -> {61}; + 61 -> {67}; 62 -> {63}; 63 -> {64}; 64 -> {65}; 65 -> {66}; 66 -> {67}; 67 -> {68}; + 68 -> {69}; } } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot index 8c851faacca..1561d1e04ba 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot @@ -8,353 +8,415 @@ subgraph foo { 0 -> {1}; } -subgraph bar { - 2 [shape=box label="Enter function bar"]; - 3 [shape=box label="Exit function bar"]; +subgraph bool { + 2 [shape=box label="Enter function bool"]; + 3 [shape=box label="Exit function bool"]; 2 -> {3}; } -subgraph baz { - 4 [shape=box label="Enter function baz"]; - 5 [shape=box label="Exit function baz"]; +subgraph bar { + 4 [shape=box label="Enter function bar"]; + 5 [shape=box label="Exit function bar"]; 4 -> {5}; } -subgraph test_1 { - 6 [shape=box label="Enter function test_1"]; - 7 [shape=box label="Enter block"]; - 8 [shape=box label="Enter when"]; - 9 [shape=box label="Enter when branch condition "]; - 10 [shape=box label="Enter &&"]; - 11 [shape=box label="Access variable R|/x|"]; - 12 [shape=box label="Type operator: x is B"]; - 13 [shape=box label="Access variable R|/x|"]; - 14 [shape=box label="Type operator: x is C"]; - 15 [shape=box label="Exit &&"]; - 16 [shape=box label="Exit when branch condition"]; - 17 [shape=box label="Enter block"]; - 18 [shape=box label="Access variable R|/x|"]; - 19 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; - 20 [shape=box label="Access variable R|/x|"]; - 21 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; - 22 [shape=box label="Access variable R|/x|"]; - 23 [shape=box label="Function call: R|/x|.R|/C.baz|()"]; - 24 [shape=box label="Exit block"]; - 25 [shape=box label="Exit when branch result"]; - 26 [shape=box label="Enter when branch condition else"]; - 27 [shape=box label="Exit when branch condition"]; - 28 [shape=box label="Enter block"]; - 29 [shape=box label="Exit block"]; - 30 [shape=box label="Exit when branch result"]; - 31 [shape=box label="Exit when"]; - 32 [shape=box label="Exit block"]; - 33 [shape=box label="Exit function test_1"]; +subgraph baz { + 6 [shape=box label="Enter function baz"]; + 7 [shape=box label="Exit function baz"]; 6 -> {7}; - 7 -> {8}; +} + +subgraph test_1 { + 8 [shape=box label="Enter function test_1"]; + 9 [shape=box label="Enter block"]; + 10 [shape=box label="Enter when"]; + 11 [shape=box label="Enter when branch condition "]; + 12 [shape=box label="Enter &&"]; + 13 [shape=box label="Access variable R|/x|"]; + 14 [shape=box label="Type operator: x is B"]; + 15 [shape=box label="Exit left part of &&"]; + 16 [shape=box label="Access variable R|/x|"]; + 17 [shape=box label="Type operator: x is C"]; + 18 [shape=box label="Exit &&"]; + 19 [shape=box label="Exit when branch condition"]; + 20 [shape=box label="Enter block"]; + 21 [shape=box label="Access variable R|/x|"]; + 22 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 23 [shape=box label="Access variable R|/x|"]; + 24 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 25 [shape=box label="Access variable R|/x|"]; + 26 [shape=box label="Function call: R|/x|.R|/C.baz|()"]; + 27 [shape=box label="Exit block"]; + 28 [shape=box label="Exit when branch result"]; + 29 [shape=box label="Enter when branch condition else"]; + 30 [shape=box label="Exit when branch condition"]; + 31 [shape=box label="Enter block"]; + 32 [shape=box label="Exit block"]; + 33 [shape=box label="Exit when branch result"]; + 34 [shape=box label="Exit when"]; + 35 [shape=box label="Exit block"]; + 36 [shape=box label="Exit function test_1"]; + 8 -> {9}; 9 -> {10}; 10 -> {11}; 11 -> {12}; - 12 -> {15 13}; + 12 -> {13}; 13 -> {14}; - 14 -> {15}; + 14 -> {18 15}; 15 -> {16}; - 16 -> {17 26}; + 16 -> {17}; 17 -> {18}; 18 -> {19}; - 19 -> {20}; + 19 -> {20 29}; 20 -> {21}; 21 -> {22}; 22 -> {23}; 23 -> {24}; 24 -> {25}; - 25 -> {31}; + 25 -> {26}; 26 -> {27}; 27 -> {28}; - 28 -> {29}; + 28 -> {34}; 29 -> {30}; 30 -> {31}; 31 -> {32}; 32 -> {33}; + 33 -> {34}; + 34 -> {35}; + 35 -> {36}; } subgraph test_2 { - 34 [shape=box label="Enter function test_2"]; - 35 [shape=box label="Enter block"]; - 36 [shape=box label="Enter when"]; - 37 [shape=box label="Enter when branch condition "]; - 38 [shape=box label="Enter ||"]; - 39 [shape=box label="Access variable R|/x|"]; - 40 [shape=box label="Type operator: x is B"]; - 41 [shape=box label="Exit left part of ||"]; + 37 [shape=box label="Enter function test_2"]; + 38 [shape=box label="Enter block"]; + 39 [shape=box label="Enter when"]; + 40 [shape=box label="Enter when branch condition "]; + 41 [shape=box label="Enter ||"]; 42 [shape=box label="Access variable R|/x|"]; - 43 [shape=box label="Type operator: x is C"]; - 44 [shape=box label="Exit ||"]; - 45 [shape=box label="Exit when branch condition"]; - 46 [shape=box label="Enter block"]; - 47 [shape=box label="Access variable R|/x|"]; - 48 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; - 49 [shape=box label="Access variable R|/x|"]; - 50 [shape=box label="Function call: R|/x|.#()"]; - 51 [shape=box label="Access variable R|/x|"]; - 52 [shape=box label="Function call: R|/x|.#()"]; - 53 [shape=box label="Exit block"]; - 54 [shape=box label="Exit when branch result"]; - 55 [shape=box label="Enter when branch condition else"]; - 56 [shape=box label="Exit when branch condition"]; - 57 [shape=box label="Enter block"]; - 58 [shape=box label="Exit block"]; - 59 [shape=box label="Exit when branch result"]; - 60 [shape=box label="Exit when"]; + 43 [shape=box label="Type operator: x is B"]; + 44 [shape=box label="Exit left part of ||"]; + 45 [shape=box label="Access variable R|/x|"]; + 46 [shape=box label="Type operator: x is C"]; + 47 [shape=box label="Exit ||"]; + 48 [shape=box label="Exit when branch condition"]; + 49 [shape=box label="Enter block"]; + 50 [shape=box label="Access variable R|/x|"]; + 51 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 52 [shape=box label="Access variable R|/x|"]; + 53 [shape=box label="Function call: R|/x|.#()"]; + 54 [shape=box label="Access variable R|/x|"]; + 55 [shape=box label="Function call: R|/x|.#()"]; + 56 [shape=box label="Exit block"]; + 57 [shape=box label="Exit when branch result"]; + 58 [shape=box label="Enter when branch condition else"]; + 59 [shape=box label="Exit when branch condition"]; + 60 [shape=box label="Enter block"]; 61 [shape=box label="Exit block"]; - 62 [shape=box label="Exit function test_2"]; + 62 [shape=box label="Exit when branch result"]; + 63 [shape=box label="Exit when"]; + 64 [shape=box label="Exit block"]; + 65 [shape=box label="Exit function test_2"]; - 34 -> {35}; - 35 -> {36}; - 36 -> {37}; 37 -> {38}; 38 -> {39}; 39 -> {40}; - 40 -> {44 41}; + 40 -> {41}; 41 -> {42}; 42 -> {43}; - 43 -> {44}; + 43 -> {47 44}; 44 -> {45}; - 45 -> {46 55}; + 45 -> {46}; 46 -> {47}; 47 -> {48}; - 48 -> {49}; + 48 -> {49 58}; 49 -> {50}; 50 -> {51}; 51 -> {52}; 52 -> {53}; 53 -> {54}; - 54 -> {60}; + 54 -> {55}; 55 -> {56}; 56 -> {57}; - 57 -> {58}; + 57 -> {63}; 58 -> {59}; 59 -> {60}; 60 -> {61}; 61 -> {62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; } subgraph test_3 { - 63 [shape=box label="Enter function test_3"]; - 64 [shape=box label="Enter block"]; - 65 [shape=box label="Enter when"]; - 66 [shape=box label="Enter when branch condition "]; - 67 [shape=box label="Access variable R|/x|"]; - 68 [shape=box label="Type operator: x !is A"]; - 69 [shape=box label="Function call: (R|/x| !is R|A|).R|kotlin/Boolean.not|()"]; - 70 [shape=box label="Exit when branch condition"]; - 71 [shape=box label="Enter block"]; - 72 [shape=box label="Access variable R|/x|"]; - 73 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; - 74 [shape=box label="Exit block"]; - 75 [shape=box label="Exit when branch result"]; - 76 [shape=box label="Enter when branch condition else"]; - 77 [shape=box label="Exit when branch condition"]; - 78 [shape=box label="Enter block"]; - 79 [shape=box label="Exit block"]; - 80 [shape=box label="Exit when branch result"]; - 81 [shape=box label="Exit when"]; + 66 [shape=box label="Enter function test_3"]; + 67 [shape=box label="Enter block"]; + 68 [shape=box label="Enter when"]; + 69 [shape=box label="Enter when branch condition "]; + 70 [shape=box label="Access variable R|/x|"]; + 71 [shape=box label="Type operator: x !is A"]; + 72 [shape=box label="Function call: (R|/x| !is R|A|).R|kotlin/Boolean.not|()"]; + 73 [shape=box label="Exit when branch condition"]; + 74 [shape=box label="Enter block"]; + 75 [shape=box label="Access variable R|/x|"]; + 76 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 77 [shape=box label="Exit block"]; + 78 [shape=box label="Exit when branch result"]; + 79 [shape=box label="Enter when branch condition else"]; + 80 [shape=box label="Exit when branch condition"]; + 81 [shape=box label="Enter block"]; 82 [shape=box label="Exit block"]; - 83 [shape=box label="Exit function test_3"]; + 83 [shape=box label="Exit when branch result"]; + 84 [shape=box label="Exit when"]; + 85 [shape=box label="Exit block"]; + 86 [shape=box label="Exit function test_3"]; - 63 -> {64}; - 64 -> {65}; - 65 -> {66}; 66 -> {67}; 67 -> {68}; 68 -> {69}; 69 -> {70}; - 70 -> {71 76}; + 70 -> {71}; 71 -> {72}; 72 -> {73}; - 73 -> {74}; + 73 -> {74 79}; 74 -> {75}; - 75 -> {81}; + 75 -> {76}; 76 -> {77}; 77 -> {78}; - 78 -> {79}; + 78 -> {84}; 79 -> {80}; 80 -> {81}; 81 -> {82}; 82 -> {83}; + 83 -> {84}; + 84 -> {85}; + 85 -> {86}; } subgraph test_4 { - 84 [shape=box label="Enter function test_4"]; - 85 [shape=box label="Enter block"]; - 86 [shape=box label="Enter when"]; - 87 [shape=box label="Enter when branch condition "]; - 88 [shape=box label="Enter ||"]; - 89 [shape=box label="Access variable R|/x|"]; - 90 [shape=box label="Type operator: x !is String"]; - 91 [shape=box label="Exit left part of ||"]; + 87 [shape=box label="Enter function test_4"]; + 88 [shape=box label="Enter block"]; + 89 [shape=box label="Enter when"]; + 90 [shape=box label="Enter when branch condition "]; + 91 [shape=box label="Enter ||"]; 92 [shape=box label="Access variable R|/x|"]; - 93 [shape=box label="Access variable R|kotlin/String.length|"]; - 94 [shape=box label="Const: Int(0)"]; - 95 [shape=box label="Operator =="]; - 96 [shape=box label="Exit ||"]; - 97 [shape=box label="Exit when branch condition"]; - 98 [shape=box label="Enter block"]; - 99 [shape=box label="Access variable R|/x|"]; - 100 [shape=box label="Access variable #"]; - 101 [shape=box label="Exit block"]; - 102 [shape=box label="Exit when branch result"]; - 103 [shape=box label="Enter when branch condition else"]; - 104 [shape=box label="Exit when branch condition"]; - 105 [shape=box label="Enter block"]; - 106 [shape=box label="Exit block"]; - 107 [shape=box label="Exit when branch result"]; - 108 [shape=box label="Exit when"]; - 109 [shape=box label="Access variable R|/x|"]; - 110 [shape=box label="Access variable #"]; - 111 [shape=box label="Exit block"]; - 112 [shape=box label="Exit function test_4"]; + 93 [shape=box label="Type operator: x !is String"]; + 94 [shape=box label="Exit left part of ||"]; + 95 [shape=box label="Access variable R|/x|"]; + 96 [shape=box label="Access variable R|kotlin/String.length|"]; + 97 [shape=box label="Const: Int(0)"]; + 98 [shape=box label="Operator =="]; + 99 [shape=box label="Exit ||"]; + 100 [shape=box label="Exit when branch condition"]; + 101 [shape=box label="Enter block"]; + 102 [shape=box label="Access variable R|/x|"]; + 103 [shape=box label="Access variable #"]; + 104 [shape=box label="Exit block"]; + 105 [shape=box label="Exit when branch result"]; + 106 [shape=box label="Enter when branch condition else"]; + 107 [shape=box label="Exit when branch condition"]; + 108 [shape=box label="Enter block"]; + 109 [shape=box label="Exit block"]; + 110 [shape=box label="Exit when branch result"]; + 111 [shape=box label="Exit when"]; + 112 [shape=box label="Access variable R|/x|"]; + 113 [shape=box label="Access variable #"]; + 114 [shape=box label="Exit block"]; + 115 [shape=box label="Exit function test_4"]; - 84 -> {85}; - 85 -> {86}; - 86 -> {87}; 87 -> {88}; 88 -> {89}; 89 -> {90}; - 90 -> {96 91}; + 90 -> {91}; 91 -> {92}; 92 -> {93}; - 93 -> {94}; + 93 -> {99 94}; 94 -> {95}; 95 -> {96}; 96 -> {97}; - 97 -> {98 103}; + 97 -> {98}; 98 -> {99}; 99 -> {100}; - 100 -> {101}; + 100 -> {101 106}; 101 -> {102}; - 102 -> {108}; + 102 -> {103}; 103 -> {104}; 104 -> {105}; - 105 -> {106}; + 105 -> {111}; 106 -> {107}; 107 -> {108}; 108 -> {109}; 109 -> {110}; 110 -> {111}; 111 -> {112}; + 112 -> {113}; + 113 -> {114}; + 114 -> {115}; } subgraph test_5 { - 113 [shape=box label="Enter function test_5"]; - 114 [shape=box label="Enter block"]; - 115 [shape=box label="Enter when"]; - 116 [shape=box label="Enter when branch condition "]; - 117 [shape=box label="Enter ||"]; - 118 [shape=box label="Access variable R|/x|"]; - 119 [shape=box label="Const: Null(null)"]; - 120 [shape=box label="Operator !="]; - 121 [shape=box label="Exit left part of ||"]; - 122 [shape=box label="Const: Boolean(false)"]; - 123 [shape=box label="Exit ||"]; - 124 [shape=box label="Exit when branch condition"]; - 125 [shape=box label="Enter block"]; - 126 [shape=box label="Access variable R|/x|"]; - 127 [shape=box label="Function call: R|/x|.#()"]; - 128 [shape=box label="Exit block"]; - 129 [shape=box label="Exit when branch result"]; - 130 [shape=box label="Enter when branch condition else"]; - 131 [shape=box label="Exit when branch condition"]; - 132 [shape=box label="Enter block"]; - 133 [shape=box label="Exit block"]; - 134 [shape=box label="Exit when branch result"]; - 135 [shape=box label="Exit when"]; + 116 [shape=box label="Enter function test_5"]; + 117 [shape=box label="Enter block"]; + 118 [shape=box label="Enter when"]; + 119 [shape=box label="Enter when branch condition "]; + 120 [shape=box label="Enter ||"]; + 121 [shape=box label="Access variable R|/x|"]; + 122 [shape=box label="Const: Null(null)"]; + 123 [shape=box label="Operator !="]; + 124 [shape=box label="Exit left part of ||"]; + 125 [shape=box label="Const: Boolean(false)"]; + 126 [shape=box label="Exit ||"]; + 127 [shape=box label="Exit when branch condition"]; + 128 [shape=box label="Enter block"]; + 129 [shape=box label="Access variable R|/x|"]; + 130 [shape=box label="Function call: R|/x|.#()"]; + 131 [shape=box label="Exit block"]; + 132 [shape=box label="Exit when branch result"]; + 133 [shape=box label="Enter when branch condition else"]; + 134 [shape=box label="Exit when branch condition"]; + 135 [shape=box label="Enter block"]; 136 [shape=box label="Exit block"]; - 137 [shape=box label="Exit function test_5"]; + 137 [shape=box label="Exit when branch result"]; + 138 [shape=box label="Exit when"]; + 139 [shape=box label="Exit block"]; + 140 [shape=box label="Exit function test_5"]; - 113 -> {114}; - 114 -> {115}; - 115 -> {116}; 116 -> {117}; 117 -> {118}; 118 -> {119}; 119 -> {120}; - 120 -> {123 121}; + 120 -> {121}; 121 -> {122}; 122 -> {123}; - 123 -> {124}; - 124 -> {125 130}; + 123 -> {126 124}; + 124 -> {125}; 125 -> {126}; 126 -> {127}; - 127 -> {128}; + 127 -> {128 133}; 128 -> {129}; - 129 -> {135}; + 129 -> {130}; 130 -> {131}; 131 -> {132}; - 132 -> {133}; + 132 -> {138}; 133 -> {134}; 134 -> {135}; 135 -> {136}; 136 -> {137}; + 137 -> {138}; + 138 -> {139}; + 139 -> {140}; } subgraph test_6 { - 138 [shape=box label="Enter function test_6"]; - 139 [shape=box label="Enter block"]; - 140 [shape=box label="Enter when"]; - 141 [shape=box label="Enter when branch condition "]; - 142 [shape=box label="Enter ||"]; - 143 [shape=box label="Const: Boolean(false)"]; - 144 [shape=box label="Exit left part of ||"]; - 145 [shape=box label="Access variable R|/x|"]; - 146 [shape=box label="Const: Null(null)"]; - 147 [shape=box label="Operator !="]; - 148 [shape=box label="Stub[DEAD]"]; - 149 [shape=box label="Exit ||"]; - 150 [shape=box label="Exit when branch condition"]; - 151 [shape=box label="Enter block"]; - 152 [shape=box label="Access variable R|/x|"]; - 153 [shape=box label="Function call: R|/x|.#()"]; - 154 [shape=box label="Exit block"]; - 155 [shape=box label="Exit when branch result"]; - 156 [shape=box label="Enter when branch condition else"]; - 157 [shape=box label="Exit when branch condition"]; - 158 [shape=box label="Enter block"]; - 159 [shape=box label="Exit block"]; - 160 [shape=box label="Exit when branch result"]; - 161 [shape=box label="Exit when"]; + 141 [shape=box label="Enter function test_6"]; + 142 [shape=box label="Enter block"]; + 143 [shape=box label="Enter when"]; + 144 [shape=box label="Enter when branch condition "]; + 145 [shape=box label="Enter ||"]; + 146 [shape=box label="Const: Boolean(false)"]; + 147 [shape=box label="Exit left part of ||"]; + 148 [shape=box label="Access variable R|/x|"]; + 149 [shape=box label="Const: Null(null)"]; + 150 [shape=box label="Operator !="]; + 151 [shape=box label="Stub[DEAD]"]; + 152 [shape=box label="Exit ||"]; + 153 [shape=box label="Exit when branch condition"]; + 154 [shape=box label="Enter block"]; + 155 [shape=box label="Access variable R|/x|"]; + 156 [shape=box label="Function call: R|/x|.#()"]; + 157 [shape=box label="Exit block"]; + 158 [shape=box label="Exit when branch result"]; + 159 [shape=box label="Enter when branch condition else"]; + 160 [shape=box label="Exit when branch condition"]; + 161 [shape=box label="Enter block"]; 162 [shape=box label="Exit block"]; - 163 [shape=box label="Exit function test_6"]; + 163 [shape=box label="Exit when branch result"]; + 164 [shape=box label="Exit when"]; + 165 [shape=box label="Exit block"]; + 166 [shape=box label="Exit function test_6"]; - 138 -> {139}; - 139 -> {140}; - 140 -> {141}; 141 -> {142}; 142 -> {143}; 143 -> {144}; - 143 -> {148} [style=dotted]; 144 -> {145}; 145 -> {146}; 146 -> {147}; - 147 -> {149}; - 148 -> {149} [style=dotted]; + 146 -> {151} [style=dotted]; + 147 -> {148}; + 148 -> {149}; 149 -> {150}; - 150 -> {151 156}; - 151 -> {152}; + 150 -> {152}; + 151 -> {152} [style=dotted]; 152 -> {153}; - 153 -> {154}; + 153 -> {154 159}; 154 -> {155}; - 155 -> {161}; + 155 -> {156}; 156 -> {157}; 157 -> {158}; - 158 -> {159}; + 158 -> {164}; 159 -> {160}; 160 -> {161}; 161 -> {162}; 162 -> {163}; + 163 -> {164}; + 164 -> {165}; + 165 -> {166}; +} + +subgraph test_7 { + 167 [shape=box label="Enter function test_7"]; + 168 [shape=box label="Enter block"]; + 169 [shape=box label="Enter when"]; + 170 [shape=box label="Enter when branch condition "]; + 171 [shape=box label="Enter &&"]; + 172 [shape=box label="Access variable R|/x|"]; + 173 [shape=box label="Type operator: x is A"]; + 174 [shape=box label="Exit left part of &&"]; + 175 [shape=box label="Access variable R|/x|"]; + 176 [shape=box label="Function call: R|/x|.R|/A.bool|()"]; + 177 [shape=box label="Exit &&"]; + 178 [shape=box label="Exit when branch condition"]; + 179 [shape=box label="Enter block"]; + 180 [shape=box label="Access variable R|/x|"]; + 181 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 182 [shape=box label="Exit block"]; + 183 [shape=box label="Exit when branch result"]; + 184 [shape=box label="Enter when branch condition else"]; + 185 [shape=box label="Exit when branch condition"]; + 186 [shape=box label="Enter block"]; + 187 [shape=box label="Exit block"]; + 188 [shape=box label="Exit when branch result"]; + 189 [shape=box label="Exit when"]; + 190 [shape=box label="Exit block"]; + 191 [shape=box label="Exit function test_7"]; + + 167 -> {168}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {173}; + 173 -> {177 174}; + 174 -> {175}; + 175 -> {176}; + 176 -> {177}; + 177 -> {178}; + 178 -> {179 184}; + 179 -> {180}; + 180 -> {181}; + 181 -> {182}; + 182 -> {183}; + 183 -> {189}; + 184 -> {185}; + 185 -> {186}; + 186 -> {187}; + 187 -> {188}; + 188 -> {189}; + 189 -> {190}; + 190 -> {191}; } } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt index 83090fd17c8..79913c76e2d 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt @@ -1,5 +1,7 @@ interface A { fun foo() + + fun bool(): Boolean } interface B : A { @@ -49,4 +51,10 @@ fun test_6(x: A?) { if (false || x != null) { x.foo() } +} + +fun test_7(x: Any) { + if (x is A && x.bool()) { + x.foo() + } } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt index 7fc7de1a1bf..5dc3d00480f 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt @@ -2,6 +2,8 @@ FILE: booleanOperators.kt public abstract interface A : R|kotlin/Any| { public abstract fun foo(): R|kotlin/Unit| + public abstract fun bool(): R|kotlin/Boolean| + } public abstract interface B : R|A| { public abstract fun bar(): R|kotlin/Unit| @@ -76,3 +78,13 @@ FILE: booleanOperators.kt } } + public final fun test_7(x: R|kotlin/Any|): R|kotlin/Unit| { + when () { + (R|/x| is R|A|) && R|/x|.R|/A.bool|() -> { + R|/x|.R|/A.foo|() + } + else -> { + } + } + + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/casts.dot b/compiler/fir/resolve/testData/resolve/smartcasts/casts.dot index f216406466a..72fd19f82f0 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/casts.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/casts.dot @@ -74,87 +74,89 @@ subgraph test_3 { 33 [shape=box label="Enter when branch condition "]; 34 [shape=box label="Enter &&"]; 35 [shape=box label="Access variable R|/b|"]; - 36 [shape=box label="Access variable R|/x|"]; - 37 [shape=box label="Type operator: x as Boolean"]; - 38 [shape=box label="Exit &&"]; - 39 [shape=box label="Exit when branch condition"]; - 40 [shape=box label="Enter block"]; - 41 [shape=box label="Access variable R|/x|"]; - 42 [shape=box label="Function call: R|/x|.R|kotlin/Boolean.not|()"]; - 43 [shape=box label="Exit block"]; - 44 [shape=box label="Exit when branch result"]; - 45 [shape=box label="Enter when branch condition else"]; - 46 [shape=box label="Exit when branch condition"]; - 47 [shape=box label="Enter block"]; - 48 [shape=box label="Exit block"]; - 49 [shape=box label="Exit when branch result"]; - 50 [shape=box label="Exit when"]; - 51 [shape=box label="Access variable R|/x|"]; - 52 [shape=box label="Function call: R|/x|.#()"]; - 53 [shape=box label="Enter when"]; - 54 [shape=box label="Enter when branch condition "]; - 55 [shape=box label="Enter &&"]; - 56 [shape=box label="Access variable R|/b|"]; - 57 [shape=box label="Access variable R|/x|"]; - 58 [shape=box label="Type operator: x as Boolean"]; - 59 [shape=box label="Const: Boolean(true)"]; - 60 [shape=box label="Operator =="]; - 61 [shape=box label="Exit &&"]; - 62 [shape=box label="Exit when branch condition"]; - 63 [shape=box label="Enter block"]; - 64 [shape=box label="Access variable R|/x|"]; - 65 [shape=box label="Function call: R|/x|.R|kotlin/Boolean.not|()"]; - 66 [shape=box label="Exit block"]; - 67 [shape=box label="Exit when branch result"]; - 68 [shape=box label="Enter when branch condition else"]; - 69 [shape=box label="Exit when branch condition"]; - 70 [shape=box label="Enter block"]; - 71 [shape=box label="Exit block"]; - 72 [shape=box label="Exit when branch result"]; - 73 [shape=box label="Exit when"]; - 74 [shape=box label="Access variable R|/x|"]; - 75 [shape=box label="Function call: R|/x|.#()"]; - 76 [shape=box label="Enter when"]; - 77 [shape=box label="Enter when branch condition "]; - 78 [shape=box label="Enter ||"]; - 79 [shape=box label="Access variable R|/b|"]; - 80 [shape=box label="Exit left part of ||"]; - 81 [shape=box label="Access variable R|/x|"]; - 82 [shape=box label="Type operator: x as Boolean"]; - 83 [shape=box label="Exit ||"]; - 84 [shape=box label="Exit when branch condition"]; - 85 [shape=box label="Enter block"]; - 86 [shape=box label="Access variable R|/x|"]; - 87 [shape=box label="Function call: R|/x|.#()"]; - 88 [shape=box label="Exit block"]; - 89 [shape=box label="Exit when branch result"]; - 90 [shape=box label="Enter when branch condition else"]; - 91 [shape=box label="Exit when branch condition"]; - 92 [shape=box label="Enter block"]; - 93 [shape=box label="Exit block"]; - 94 [shape=box label="Exit when branch result"]; - 95 [shape=box label="Exit when"]; - 96 [shape=box label="Access variable R|/x|"]; - 97 [shape=box label="Function call: R|/x|.#()"]; - 98 [shape=box label="Exit block"]; - 99 [shape=box label="Exit function test_3"]; + 36 [shape=box label="Exit left part of &&"]; + 37 [shape=box label="Access variable R|/x|"]; + 38 [shape=box label="Type operator: x as Boolean"]; + 39 [shape=box label="Exit &&"]; + 40 [shape=box label="Exit when branch condition"]; + 41 [shape=box label="Enter block"]; + 42 [shape=box label="Access variable R|/x|"]; + 43 [shape=box label="Function call: R|/x|.R|kotlin/Boolean.not|()"]; + 44 [shape=box label="Exit block"]; + 45 [shape=box label="Exit when branch result"]; + 46 [shape=box label="Enter when branch condition else"]; + 47 [shape=box label="Exit when branch condition"]; + 48 [shape=box label="Enter block"]; + 49 [shape=box label="Exit block"]; + 50 [shape=box label="Exit when branch result"]; + 51 [shape=box label="Exit when"]; + 52 [shape=box label="Access variable R|/x|"]; + 53 [shape=box label="Function call: R|/x|.#()"]; + 54 [shape=box label="Enter when"]; + 55 [shape=box label="Enter when branch condition "]; + 56 [shape=box label="Enter &&"]; + 57 [shape=box label="Access variable R|/b|"]; + 58 [shape=box label="Exit left part of &&"]; + 59 [shape=box label="Access variable R|/x|"]; + 60 [shape=box label="Type operator: x as Boolean"]; + 61 [shape=box label="Const: Boolean(true)"]; + 62 [shape=box label="Operator =="]; + 63 [shape=box label="Exit &&"]; + 64 [shape=box label="Exit when branch condition"]; + 65 [shape=box label="Enter block"]; + 66 [shape=box label="Access variable R|/x|"]; + 67 [shape=box label="Function call: R|/x|.R|kotlin/Boolean.not|()"]; + 68 [shape=box label="Exit block"]; + 69 [shape=box label="Exit when branch result"]; + 70 [shape=box label="Enter when branch condition else"]; + 71 [shape=box label="Exit when branch condition"]; + 72 [shape=box label="Enter block"]; + 73 [shape=box label="Exit block"]; + 74 [shape=box label="Exit when branch result"]; + 75 [shape=box label="Exit when"]; + 76 [shape=box label="Access variable R|/x|"]; + 77 [shape=box label="Function call: R|/x|.#()"]; + 78 [shape=box label="Enter when"]; + 79 [shape=box label="Enter when branch condition "]; + 80 [shape=box label="Enter ||"]; + 81 [shape=box label="Access variable R|/b|"]; + 82 [shape=box label="Exit left part of ||"]; + 83 [shape=box label="Access variable R|/x|"]; + 84 [shape=box label="Type operator: x as Boolean"]; + 85 [shape=box label="Exit ||"]; + 86 [shape=box label="Exit when branch condition"]; + 87 [shape=box label="Enter block"]; + 88 [shape=box label="Access variable R|/x|"]; + 89 [shape=box label="Function call: R|/x|.#()"]; + 90 [shape=box label="Exit block"]; + 91 [shape=box label="Exit when branch result"]; + 92 [shape=box label="Enter when branch condition else"]; + 93 [shape=box label="Exit when branch condition"]; + 94 [shape=box label="Enter block"]; + 95 [shape=box label="Exit block"]; + 96 [shape=box label="Exit when branch result"]; + 97 [shape=box label="Exit when"]; + 98 [shape=box label="Access variable R|/x|"]; + 99 [shape=box label="Function call: R|/x|.#()"]; + 100 [shape=box label="Exit block"]; + 101 [shape=box label="Exit function test_3"]; 30 -> {31}; 31 -> {32}; 32 -> {33}; 33 -> {34}; 34 -> {35}; - 35 -> {38 36}; + 35 -> {39 36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40 45}; - 40 -> {41}; + 39 -> {40}; + 40 -> {41 46}; 41 -> {42}; 42 -> {43}; 43 -> {44}; - 44 -> {50}; - 45 -> {46}; + 44 -> {45}; + 45 -> {51}; 46 -> {47}; 47 -> {48}; 48 -> {49}; @@ -165,20 +167,20 @@ subgraph test_3 { 53 -> {54}; 54 -> {55}; 55 -> {56}; - 56 -> {61 57}; - 57 -> {58}; + 56 -> {57}; + 57 -> {63 58}; 58 -> {59}; 59 -> {60}; 60 -> {61}; 61 -> {62}; - 62 -> {63 68}; + 62 -> {63}; 63 -> {64}; - 64 -> {65}; + 64 -> {65 70}; 65 -> {66}; 66 -> {67}; - 67 -> {73}; + 67 -> {68}; 68 -> {69}; - 69 -> {70}; + 69 -> {75}; 70 -> {71}; 71 -> {72}; 72 -> {73}; @@ -188,19 +190,19 @@ subgraph test_3 { 76 -> {77}; 77 -> {78}; 78 -> {79}; - 79 -> {83 80}; + 79 -> {80}; 80 -> {81}; - 81 -> {82}; + 81 -> {85 82}; 82 -> {83}; 83 -> {84}; - 84 -> {85 90}; + 84 -> {85}; 85 -> {86}; - 86 -> {87}; + 86 -> {87 92}; 87 -> {88}; 88 -> {89}; - 89 -> {95}; + 89 -> {90}; 90 -> {91}; - 91 -> {92}; + 91 -> {97}; 92 -> {93}; 93 -> {94}; 94 -> {95}; @@ -208,74 +210,74 @@ subgraph test_3 { 96 -> {97}; 97 -> {98}; 98 -> {99}; + 99 -> {100}; + 100 -> {101}; } subgraph test_4 { - 100 [shape=box label="Enter function test_4"]; - 101 [shape=box label="Enter block"]; - 102 [shape=box label="Enter when"]; - 103 [shape=box label="Enter when branch condition "]; - 104 [shape=box label="Access variable R|/b|"]; - 105 [shape=box label="Type operator: b as? Boolean"]; - 106 [shape=box label="Const: Null(null)"]; - 107 [shape=box label="Operator !="]; - 108 [shape=box label="Exit when branch condition"]; - 109 [shape=box label="Enter block"]; - 110 [shape=box label="Access variable R|/b|"]; - 111 [shape=box label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; - 112 [shape=box label="Exit block"]; - 113 [shape=box label="Exit when branch result"]; - 114 [shape=box label="Enter when branch condition else"]; - 115 [shape=box label="Exit when branch condition"]; - 116 [shape=box label="Enter block"]; - 117 [shape=box label="Access variable R|/b|"]; - 118 [shape=box label="Function call: R|/b|.#()"]; - 119 [shape=box label="Exit block"]; - 120 [shape=box label="Exit when branch result"]; - 121 [shape=box label="Exit when"]; - 122 [shape=box label="Access variable R|/b|"]; - 123 [shape=box label="Function call: R|/b|.#()"]; - 124 [shape=box label="Enter when"]; - 125 [shape=box label="Enter when branch condition "]; - 126 [shape=box label="Access variable R|/b|"]; - 127 [shape=box label="Type operator: b as? Boolean"]; - 128 [shape=box label="Const: Null(null)"]; - 129 [shape=box label="Operator =="]; - 130 [shape=box label="Exit when branch condition"]; - 131 [shape=box label="Enter block"]; - 132 [shape=box label="Access variable R|/b|"]; - 133 [shape=box label="Function call: R|/b|.#()"]; - 134 [shape=box label="Exit block"]; - 135 [shape=box label="Exit when branch result"]; - 136 [shape=box label="Enter when branch condition else"]; - 137 [shape=box label="Exit when branch condition"]; - 138 [shape=box label="Enter block"]; - 139 [shape=box label="Access variable R|/b|"]; - 140 [shape=box label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; - 141 [shape=box label="Exit block"]; - 142 [shape=box label="Exit when branch result"]; - 143 [shape=box label="Exit when"]; - 144 [shape=box label="Access variable R|/b|"]; - 145 [shape=box label="Function call: R|/b|.#()"]; - 146 [shape=box label="Exit block"]; - 147 [shape=box label="Exit function test_4"]; + 102 [shape=box label="Enter function test_4"]; + 103 [shape=box label="Enter block"]; + 104 [shape=box label="Enter when"]; + 105 [shape=box label="Enter when branch condition "]; + 106 [shape=box label="Access variable R|/b|"]; + 107 [shape=box label="Type operator: b as? Boolean"]; + 108 [shape=box label="Const: Null(null)"]; + 109 [shape=box label="Operator !="]; + 110 [shape=box label="Exit when branch condition"]; + 111 [shape=box label="Enter block"]; + 112 [shape=box label="Access variable R|/b|"]; + 113 [shape=box label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; + 114 [shape=box label="Exit block"]; + 115 [shape=box label="Exit when branch result"]; + 116 [shape=box label="Enter when branch condition else"]; + 117 [shape=box label="Exit when branch condition"]; + 118 [shape=box label="Enter block"]; + 119 [shape=box label="Access variable R|/b|"]; + 120 [shape=box label="Function call: R|/b|.#()"]; + 121 [shape=box label="Exit block"]; + 122 [shape=box label="Exit when branch result"]; + 123 [shape=box label="Exit when"]; + 124 [shape=box label="Access variable R|/b|"]; + 125 [shape=box label="Function call: R|/b|.#()"]; + 126 [shape=box label="Enter when"]; + 127 [shape=box label="Enter when branch condition "]; + 128 [shape=box label="Access variable R|/b|"]; + 129 [shape=box label="Type operator: b as? Boolean"]; + 130 [shape=box label="Const: Null(null)"]; + 131 [shape=box label="Operator =="]; + 132 [shape=box label="Exit when branch condition"]; + 133 [shape=box label="Enter block"]; + 134 [shape=box label="Access variable R|/b|"]; + 135 [shape=box label="Function call: R|/b|.#()"]; + 136 [shape=box label="Exit block"]; + 137 [shape=box label="Exit when branch result"]; + 138 [shape=box label="Enter when branch condition else"]; + 139 [shape=box label="Exit when branch condition"]; + 140 [shape=box label="Enter block"]; + 141 [shape=box label="Access variable R|/b|"]; + 142 [shape=box label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; + 143 [shape=box label="Exit block"]; + 144 [shape=box label="Exit when branch result"]; + 145 [shape=box label="Exit when"]; + 146 [shape=box label="Access variable R|/b|"]; + 147 [shape=box label="Function call: R|/b|.#()"]; + 148 [shape=box label="Exit block"]; + 149 [shape=box label="Exit function test_4"]; - 100 -> {101}; - 101 -> {102}; 102 -> {103}; 103 -> {104}; 104 -> {105}; 105 -> {106}; 106 -> {107}; 107 -> {108}; - 108 -> {109 114}; + 108 -> {109}; 109 -> {110}; - 110 -> {111}; + 110 -> {111 116}; 111 -> {112}; 112 -> {113}; - 113 -> {121}; + 113 -> {114}; 114 -> {115}; - 115 -> {116}; + 115 -> {123}; 116 -> {117}; 117 -> {118}; 118 -> {119}; @@ -290,14 +292,14 @@ subgraph test_4 { 127 -> {128}; 128 -> {129}; 129 -> {130}; - 130 -> {131 136}; + 130 -> {131}; 131 -> {132}; - 132 -> {133}; + 132 -> {133 138}; 133 -> {134}; 134 -> {135}; - 135 -> {143}; + 135 -> {136}; 136 -> {137}; - 137 -> {138}; + 137 -> {145}; 138 -> {139}; 139 -> {140}; 140 -> {141}; @@ -307,6 +309,8 @@ subgraph test_4 { 144 -> {145}; 145 -> {146}; 146 -> {147}; + 147 -> {148}; + 148 -> {149}; } }