diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot index b4d4218079b..9defb656f84 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot @@ -853,16 +853,16 @@ digraph flowFromInplaceLambda2_kt { 303 [label="Postponed enter to lambda"]; subgraph cluster_71 { color=blue - 320 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 321 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_72 { color=blue - 321 [label="Enter block"]; - 322 [label="Const: Null(null)"]; - 323 [label="Assignment: R|/p|"]; - 324 [label="Function call: R|/n|()"]; - 325 [label="Exit block"]; + 322 [label="Enter block"]; + 323 [label="Const: Null(null)"]; + 324 [label="Assignment: R|/p|"]; + 325 [label="Function call: R|/n|()"]; + 326 [label="Exit block"]; } - 326 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 327 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 304 [label="Postponed exit from lambda"]; 305 [label="Function call: R|kotlin/run|(...)"]; @@ -871,32 +871,33 @@ digraph flowFromInplaceLambda2_kt { 308 [label="Postponed enter to lambda"]; subgraph cluster_73 { color=blue - 327 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 328 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_74 { color=blue - 328 [label="Enter block"]; - 329 [label="Access variable R|/p|"]; - 330 [label="Smart cast: R|/p|"]; - 331 [label="Access variable #"]; - 332 [label="Const: Int(123)"]; - 333 [label="Exit block"]; + 329 [label="Enter block"]; + 330 [label="Access variable R|/p|"]; + 331 [label="Smart cast: R|/p|"]; + 332 [label="Access variable #"]; + 333 [label="Const: Int(123)"]; + 334 [label="Exit block"]; } - 334 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 335 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 309 [label="Postponed exit from lambda"]; 310 [label="Function call: R|kotlin/run|(...)"]; 311 [label="Call arguments union" style="filled" fillcolor=yellow]; 312 [label="Function call: R|/foo|(...)"]; 313 [label="Access variable R|/p|"]; - 314 [label="Access variable #"]; - 315 [label="Exit block"]; + 314 [label="Smart cast: R|/p|"]; + 315 [label="Access variable #"]; + 316 [label="Exit block"]; } - 316 [label="Exit when branch result"]; - 317 [label="Exit when"]; + 317 [label="Exit when branch result"]; + 318 [label="Exit when"]; } - 318 [label="Exit block"]; + 319 [label="Exit block"]; } - 319 [label="Exit function test7" style="filled" fillcolor=red]; + 320 [label="Exit function test7" style="filled" fillcolor=red]; } 290 -> {291}; 291 -> {292}; @@ -908,19 +909,19 @@ digraph flowFromInplaceLambda2_kt { 297 -> {298}; 298 -> {299}; 299 -> {301 300}; - 300 -> {317}; + 300 -> {318}; 301 -> {302}; 302 -> {303}; - 303 -> {320}; + 303 -> {321}; 303 -> {304} [color=red]; - 303 -> {320} [style=dashed]; + 303 -> {321} [style=dashed]; 304 -> {305}; 305 -> {306}; 306 -> {307}; 307 -> {308}; - 308 -> {327}; + 308 -> {328}; 308 -> {309} [color=red]; - 308 -> {327} [style=dashed]; + 308 -> {328} [style=dashed]; 309 -> {310}; 310 -> {311}; 311 -> {312}; @@ -931,22 +932,23 @@ digraph flowFromInplaceLambda2_kt { 316 -> {317}; 317 -> {318}; 318 -> {319}; - 320 -> {321}; + 319 -> {320}; 321 -> {322}; 322 -> {323}; 323 -> {324}; 324 -> {325}; 325 -> {326}; - 326 -> {311} [color=red]; - 326 -> {304} [color=green]; - 327 -> {328}; + 326 -> {327}; + 327 -> {311} [color=red]; + 327 -> {304} [color=green]; 328 -> {329}; 329 -> {330}; 330 -> {331}; 331 -> {332}; 332 -> {333}; 333 -> {334}; - 334 -> {311} [color=red]; - 334 -> {309} [color=green]; + 334 -> {335}; + 335 -> {311} [color=red]; + 335 -> {309} [color=green]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot index df5dab8ca9f..d7f3d824534 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot @@ -69,46 +69,47 @@ digraph flowFromTwoInplaceLambdas_kt { 26 [label="Postponed enter to lambda"]; subgraph cluster_9 { color=blue - 39 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_10 { color=blue - 40 [label="Enter block"]; - 41 [label="Const: Null(null)"]; - 42 [label="Assignment: R|/p|"]; - 43 [label="Function call: R|/n|()"]; - 44 [label="Exit block"]; + 41 [label="Enter block"]; + 42 [label="Const: Null(null)"]; + 43 [label="Assignment: R|/p|"]; + 44 [label="Function call: R|/n|()"]; + 45 [label="Exit block"]; } - 45 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 46 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 28 [label="Postponed exit from lambda"]; 29 [label="Postponed enter to lambda"]; subgraph cluster_11 { color=blue - 46 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 47 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_12 { color=blue - 47 [label="Enter block"]; - 48 [label="Access variable R|/p|"]; - 49 [label="Smart cast: R|/p|"]; - 50 [label="Access variable #"]; - 51 [label="Const: Int(123)"]; - 52 [label="Exit block"]; + 48 [label="Enter block"]; + 49 [label="Access variable R|/p|"]; + 50 [label="Smart cast: R|/p|"]; + 51 [label="Access variable #"]; + 52 [label="Const: Int(123)"]; + 53 [label="Exit block"]; } - 53 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 54 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 27 [label="Call arguments union" style="filled" fillcolor=yellow]; 30 [label="Postponed exit from lambda"]; 31 [label="Function call: R|/run2|(...)"]; 32 [label="Access variable R|/p|"]; - 33 [label="Access variable #"]; - 34 [label="Exit block"]; + 33 [label="Smart cast: R|/p|"]; + 34 [label="Access variable #"]; + 35 [label="Exit block"]; } - 35 [label="Exit when branch result"]; - 36 [label="Exit when"]; + 36 [label="Exit when branch result"]; + 37 [label="Exit when"]; } - 37 [label="Exit block"]; + 38 [label="Exit block"]; } - 38 [label="Exit function test1" style="filled" fillcolor=red]; + 39 [label="Exit function test1" style="filled" fillcolor=red]; } 13 -> {14}; 14 -> {15}; @@ -120,17 +121,17 @@ digraph flowFromTwoInplaceLambdas_kt { 20 -> {21}; 21 -> {22}; 22 -> {24 23}; - 23 -> {36}; + 23 -> {37}; 24 -> {25}; 25 -> {26}; - 26 -> {39}; + 26 -> {40}; 26 -> {28} [color=red]; - 26 -> {39} [style=dashed]; + 26 -> {40} [style=dashed]; 27 -> {31} [color=red]; 28 -> {29}; - 29 -> {46}; + 29 -> {47}; 29 -> {30} [color=red]; - 29 -> {46} [style=dashed]; + 29 -> {47} [style=dashed]; 30 -> {31} [color=green]; 31 -> {32}; 32 -> {33}; @@ -139,93 +140,94 @@ digraph flowFromTwoInplaceLambdas_kt { 35 -> {36}; 36 -> {37}; 37 -> {38}; - 39 -> {40}; + 38 -> {39}; 40 -> {41}; 41 -> {42}; 42 -> {43}; 43 -> {44}; 44 -> {45}; - 45 -> {27} [color=red]; - 45 -> {28} [color=green]; - 46 -> {47}; + 45 -> {46}; + 46 -> {27} [color=red]; + 46 -> {28} [color=green]; 47 -> {48}; 48 -> {49}; 49 -> {50}; 50 -> {51}; 51 -> {52}; 52 -> {53}; - 53 -> {27} [color=red]; - 53 -> {30} [color=green]; + 53 -> {54}; + 54 -> {27} [color=red]; + 54 -> {30} [color=green]; subgraph cluster_13 { color=red - 54 [label="Enter function test1_tail" style="filled" fillcolor=red]; + 55 [label="Enter function test1_tail" style="filled" fillcolor=red]; subgraph cluster_14 { color=blue - 55 [label="Enter block"]; - 56 [label="Access variable R|/x|"]; - 57 [label="Variable declaration: lvar p: R|kotlin/String?|"]; + 56 [label="Enter block"]; + 57 [label="Access variable R|/x|"]; + 58 [label="Variable declaration: lvar p: R|kotlin/String?|"]; subgraph cluster_15 { color=blue - 58 [label="Enter when"]; + 59 [label="Enter when"]; subgraph cluster_16 { color=blue - 59 [label="Enter when branch condition "]; - 60 [label="Access variable R|/p|"]; - 61 [label="Const: Null(null)"]; - 62 [label="Equality operator !="]; - 63 [label="Exit when branch condition"]; + 60 [label="Enter when branch condition "]; + 61 [label="Access variable R|/p|"]; + 62 [label="Const: Null(null)"]; + 63 [label="Equality operator !="]; + 64 [label="Exit when branch condition"]; } - 64 [label="Synthetic else branch"]; - 65 [label="Enter when branch result"]; + 65 [label="Synthetic else branch"]; + 66 [label="Enter when branch result"]; subgraph cluster_17 { color=blue - 66 [label="Enter block"]; - 67 [label="Postponed enter to lambda"]; + 67 [label="Enter block"]; + 68 [label="Postponed enter to lambda"]; subgraph cluster_18 { color=blue - 87 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 89 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_19 { color=blue - 88 [label="Enter block"]; - 89 [label="Access variable R|/p|"]; - 90 [label="Smart cast: R|/p|"]; - 91 [label="Access variable #"]; - 92 [label="Const: Int(123)"]; - 93 [label="Exit block"]; + 90 [label="Enter block"]; + 91 [label="Access variable R|/p|"]; + 92 [label="Smart cast: R|/p|"]; + 93 [label="Access variable #"]; + 94 [label="Const: Int(123)"]; + 95 [label="Exit block"]; } - 94 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 96 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 69 [label="Postponed exit from lambda"]; - 70 [label="Postponed enter to lambda"]; + 70 [label="Postponed exit from lambda"]; + 71 [label="Postponed enter to lambda"]; subgraph cluster_20 { color=blue - 80 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 82 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_21 { color=blue - 81 [label="Enter block"]; - 82 [label="Const: Null(null)"]; - 83 [label="Assignment: R|/p|"]; - 84 [label="Function call: R|/n|()"]; - 85 [label="Exit block"]; + 83 [label="Enter block"]; + 84 [label="Const: Null(null)"]; + 85 [label="Assignment: R|/p|"]; + 86 [label="Function call: R|/n|()"]; + 87 [label="Exit block"]; } - 86 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 88 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 68 [label="Call arguments union" style="filled" fillcolor=yellow]; - 71 [label="Postponed exit from lambda"]; - 72 [label="Function call: R|/run2|(...)"]; - 73 [label="Access variable R|/p|"]; - 74 [label="Access variable #"]; - 75 [label="Exit block"]; + 69 [label="Call arguments union" style="filled" fillcolor=yellow]; + 72 [label="Postponed exit from lambda"]; + 73 [label="Function call: R|/run2|(...)"]; + 74 [label="Access variable R|/p|"]; + 75 [label="Smart cast: R|/p|"]; + 76 [label="Access variable #"]; + 77 [label="Exit block"]; } - 76 [label="Exit when branch result"]; - 77 [label="Exit when"]; + 78 [label="Exit when branch result"]; + 79 [label="Exit when"]; } - 78 [label="Exit block"]; + 80 [label="Exit block"]; } - 79 [label="Exit function test1_tail" style="filled" fillcolor=red]; + 81 [label="Exit function test1_tail" style="filled" fillcolor=red]; } - 54 -> {55}; 55 -> {56}; 56 -> {57}; 57 -> {58}; @@ -234,333 +236,333 @@ digraph flowFromTwoInplaceLambdas_kt { 60 -> {61}; 61 -> {62}; 62 -> {63}; - 63 -> {65 64}; - 64 -> {77}; - 65 -> {66}; + 63 -> {64}; + 64 -> {66 65}; + 65 -> {79}; 66 -> {67}; - 67 -> {87}; - 67 -> {69} [color=red]; - 67 -> {87} [style=dashed]; - 68 -> {72} [color=red]; - 69 -> {70}; - 70 -> {80}; - 70 -> {71} [color=red]; - 70 -> {80} [style=dashed]; - 71 -> {72} [color=green]; - 72 -> {73}; + 67 -> {68}; + 68 -> {89}; + 68 -> {70} [color=red]; + 68 -> {89} [style=dashed]; + 69 -> {73} [color=red]; + 70 -> {71}; + 71 -> {82}; + 71 -> {72} [color=red]; + 71 -> {82} [style=dashed]; + 72 -> {73} [color=green]; 73 -> {74}; 74 -> {75}; 75 -> {76}; 76 -> {77}; 77 -> {78}; 78 -> {79}; + 79 -> {80}; 80 -> {81}; - 81 -> {82}; 82 -> {83}; 83 -> {84}; 84 -> {85}; 85 -> {86}; - 86 -> {68} [color=red]; - 86 -> {71} [color=green]; + 86 -> {87}; 87 -> {88}; - 88 -> {89}; + 88 -> {69} [color=red]; + 88 -> {72} [color=green]; 89 -> {90}; 90 -> {91}; 91 -> {92}; 92 -> {93}; 93 -> {94}; - 94 -> {68} [color=red]; - 94 -> {69} [color=green]; + 94 -> {95}; + 95 -> {96}; + 96 -> {69} [color=red]; + 96 -> {70} [color=green]; subgraph cluster_22 { color=red - 95 [label="Enter function test2" style="filled" fillcolor=red]; + 97 [label="Enter function test2" style="filled" fillcolor=red]; subgraph cluster_23 { color=blue - 96 [label="Enter block"]; - 97 [label="Access variable R|/x|"]; - 98 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; - 99 [label="Access variable R|/p|"]; - 100 [label="Access variable #"]; - 101 [label="Postponed enter to lambda"]; + 98 [label="Enter block"]; + 99 [label="Access variable R|/x|"]; + 100 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 101 [label="Access variable R|/p|"]; + 102 [label="Access variable #"]; + 103 [label="Postponed enter to lambda"]; subgraph cluster_24 { color=blue - 117 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 119 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_25 { color=blue - 118 [label="Enter block"]; - 119 [label="Const: Null(null)"]; - 120 [label="Assignment: R|/p|"]; - 121 [label="Function call: R|/n|()"]; - 122 [label="Exit block"]; + 120 [label="Enter block"]; + 121 [label="Const: Null(null)"]; + 122 [label="Assignment: R|/p|"]; + 123 [label="Function call: R|/n|()"]; + 124 [label="Exit block"]; } - 123 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 125 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 103 [label="Postponed exit from lambda"]; - 104 [label="Postponed enter to lambda"]; + 105 [label="Postponed exit from lambda"]; + 106 [label="Postponed enter to lambda"]; subgraph cluster_26 { color=blue - 124 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 126 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_27 { color=blue - 125 [label="Enter block"]; - 126 [label="Access variable R|/p|"]; - 127 [label="Type operator: (R|/p| as R|kotlin/String|)"]; - 128 [label="Const: Int(123)"]; - 129 [label="Exit block"]; + 127 [label="Enter block"]; + 128 [label="Access variable R|/p|"]; + 129 [label="Type operator: (R|/p| as R|kotlin/String|)"]; + 130 [label="Const: Int(123)"]; + 131 [label="Exit block"]; } - 130 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 132 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 102 [label="Call arguments union" style="filled" fillcolor=yellow]; - 105 [label="Postponed exit from lambda"]; - 106 [label="Function call: R|/run2|(...)"]; - 107 [label="Access variable R|/p|"]; - 108 [label="Smart cast: R|/p|"]; - 109 [label="Access variable #"]; - 110 [label="Access variable R|/p|"]; - 111 [label="Smart cast: R|/p|"]; - 112 [label="Enter safe call"]; - 113 [label="Access variable R|kotlin/String.length|"]; - 114 [label="Exit safe call"]; - 115 [label="Exit block"]; + 104 [label="Call arguments union" style="filled" fillcolor=yellow]; + 107 [label="Postponed exit from lambda"]; + 108 [label="Function call: R|/run2|(...)"]; + 109 [label="Access variable R|/p|"]; + 110 [label="Smart cast: R|/p|"]; + 111 [label="Access variable #"]; + 112 [label="Access variable R|/p|"]; + 113 [label="Smart cast: R|/p|"]; + 114 [label="Enter safe call"]; + 115 [label="Access variable #"]; + 116 [label="Exit safe call"]; + 117 [label="Exit block"]; } - 116 [label="Exit function test2" style="filled" fillcolor=red]; + 118 [label="Exit function test2" style="filled" fillcolor=red]; } - 95 -> {96}; - 96 -> {97}; 97 -> {98}; 98 -> {99}; 99 -> {100}; 100 -> {101}; - 101 -> {117}; - 101 -> {103} [color=red]; - 101 -> {117} [style=dashed]; - 102 -> {106} [color=red]; - 103 -> {104}; - 104 -> {124}; - 104 -> {105} [color=red]; - 104 -> {124} [style=dashed]; - 105 -> {106} [color=green]; - 106 -> {107}; - 107 -> {108}; + 101 -> {102}; + 102 -> {103}; + 103 -> {119}; + 103 -> {105} [color=red]; + 103 -> {119} [style=dashed]; + 104 -> {108} [color=red]; + 105 -> {106}; + 106 -> {126}; + 106 -> {107} [color=red]; + 106 -> {126} [style=dashed]; + 107 -> {108} [color=green]; 108 -> {109}; 109 -> {110}; 110 -> {111}; - 111 -> {112 114}; + 111 -> {112}; 112 -> {113}; - 113 -> {114}; + 113 -> {114 116}; 114 -> {115}; 115 -> {116}; + 116 -> {117}; 117 -> {118}; - 118 -> {119}; 119 -> {120}; 120 -> {121}; 121 -> {122}; 122 -> {123}; - 123 -> {102} [color=red]; - 123 -> {103} [color=green]; + 123 -> {124}; 124 -> {125}; - 125 -> {126}; + 125 -> {104} [color=red]; + 125 -> {105} [color=green]; 126 -> {127}; 127 -> {128}; 128 -> {129}; 129 -> {130}; - 130 -> {102} [color=red]; - 130 -> {105} [color=green]; + 130 -> {131}; + 131 -> {132}; + 132 -> {104} [color=red]; + 132 -> {107} [color=green]; subgraph cluster_28 { color=red - 131 [label="Enter function test3" style="filled" fillcolor=red]; + 133 [label="Enter function test3" style="filled" fillcolor=red]; subgraph cluster_29 { color=blue - 132 [label="Enter block"]; - 133 [label="Access variable R|/x|"]; - 134 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; - 135 [label="Access variable R|/p|"]; - 136 [label="Access variable #"]; - 137 [label="Postponed enter to lambda"]; + 134 [label="Enter block"]; + 135 [label="Access variable R|/x|"]; + 136 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 137 [label="Access variable R|/p|"]; + 138 [label="Access variable #"]; + 139 [label="Postponed enter to lambda"]; subgraph cluster_30 { color=blue - 153 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 155 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_31 { color=blue - 154 [label="Enter block"]; - 155 [label="Const: Null(null)"]; - 156 [label="Assignment: R|/p|"]; - 157 [label="Function call: R|/n|()"]; - 158 [label="Exit block"]; + 156 [label="Enter block"]; + 157 [label="Const: Null(null)"]; + 158 [label="Assignment: R|/p|"]; + 159 [label="Function call: R|/n|()"]; + 160 [label="Exit block"]; } - 159 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 161 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 139 [label="Postponed exit from lambda"]; - 140 [label="Postponed enter to lambda"]; + 141 [label="Postponed exit from lambda"]; + 142 [label="Postponed enter to lambda"]; subgraph cluster_32 { color=blue - 160 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 162 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_33 { color=blue - 161 [label="Enter block"]; - 162 [label="Const: String()"]; - 163 [label="Assignment: R|/p|"]; - 164 [label="Const: Int(123)"]; - 165 [label="Exit block"]; + 163 [label="Enter block"]; + 164 [label="Const: String()"]; + 165 [label="Assignment: R|/p|"]; + 166 [label="Const: Int(123)"]; + 167 [label="Exit block"]; } - 166 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 168 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 138 [label="Call arguments union" style="filled" fillcolor=yellow]; - 141 [label="Postponed exit from lambda"]; - 142 [label="Function call: R|/run2|(...)"]; - 143 [label="Access variable R|/p|"]; - 144 [label="Smart cast: R|/p|"]; - 145 [label="Access variable #"]; - 146 [label="Access variable R|/p|"]; - 147 [label="Smart cast: R|/p|"]; - 148 [label="Enter safe call"]; - 149 [label="Access variable R|kotlin/String.length|"]; - 150 [label="Exit safe call"]; - 151 [label="Exit block"]; + 140 [label="Call arguments union" style="filled" fillcolor=yellow]; + 143 [label="Postponed exit from lambda"]; + 144 [label="Function call: R|/run2|(...)"]; + 145 [label="Access variable R|/p|"]; + 146 [label="Smart cast: R|/p|"]; + 147 [label="Access variable #"]; + 148 [label="Access variable R|/p|"]; + 149 [label="Smart cast: R|/p|"]; + 150 [label="Enter safe call"]; + 151 [label="Access variable R|kotlin/String.length|"]; + 152 [label="Exit safe call"]; + 153 [label="Exit block"]; } - 152 [label="Exit function test3" style="filled" fillcolor=red]; + 154 [label="Exit function test3" style="filled" fillcolor=red]; } - 131 -> {132}; - 132 -> {133}; 133 -> {134}; 134 -> {135}; 135 -> {136}; 136 -> {137}; - 137 -> {153}; - 137 -> {139} [color=red]; - 137 -> {153} [style=dashed]; - 138 -> {142} [color=red]; - 139 -> {140}; - 140 -> {160}; - 140 -> {141} [color=red]; - 140 -> {160} [style=dashed]; - 141 -> {142} [color=green]; - 142 -> {143}; - 143 -> {144}; + 137 -> {138}; + 138 -> {139}; + 139 -> {155}; + 139 -> {141} [color=red]; + 139 -> {155} [style=dashed]; + 140 -> {144} [color=red]; + 141 -> {142}; + 142 -> {162}; + 142 -> {143} [color=red]; + 142 -> {162} [style=dashed]; + 143 -> {144} [color=green]; 144 -> {145}; 145 -> {146}; 146 -> {147}; - 147 -> {148 150}; + 147 -> {148}; 148 -> {149}; - 149 -> {150}; + 149 -> {150 152}; 150 -> {151}; 151 -> {152}; + 152 -> {153}; 153 -> {154}; - 154 -> {155}; 155 -> {156}; 156 -> {157}; 157 -> {158}; 158 -> {159}; - 159 -> {138} [color=red]; - 159 -> {139} [color=green]; + 159 -> {160}; 160 -> {161}; - 161 -> {162}; + 161 -> {140} [color=red]; + 161 -> {141} [color=green]; 162 -> {163}; 163 -> {164}; 164 -> {165}; 165 -> {166}; - 166 -> {138} [color=red]; - 166 -> {141} [color=green]; + 166 -> {167}; + 167 -> {168}; + 168 -> {140} [color=red]; + 168 -> {143} [color=green]; subgraph cluster_34 { color=red - 167 [label="Enter class I1" style="filled" fillcolor=red]; - 168 [label="Exit class I1" style="filled" fillcolor=red]; - } - 167 -> {168} [color=green]; - - subgraph cluster_35 { - color=red - 169 [label="Enter class I2" style="filled" fillcolor=red]; - 170 [label="Exit class I2" style="filled" fillcolor=red]; + 169 [label="Enter class I1" style="filled" fillcolor=red]; + 170 [label="Exit class I1" style="filled" fillcolor=red]; } 169 -> {170} [color=green]; + subgraph cluster_35 { + color=red + 171 [label="Enter class I2" style="filled" fillcolor=red]; + 172 [label="Exit class I2" style="filled" fillcolor=red]; + } + 171 -> {172} [color=green]; + subgraph cluster_36 { color=red - 171 [label="Enter function test4" style="filled" fillcolor=red]; + 173 [label="Enter function test4" style="filled" fillcolor=red]; subgraph cluster_37 { color=blue - 172 [label="Enter block"]; - 173 [label="Access variable R|/x|"]; - 174 [label="Access variable #"]; + 174 [label="Enter block"]; 175 [label="Access variable R|/x|"]; - 176 [label="Access variable #"]; - 177 [label="Postponed enter to lambda"]; + 176 [label="Access variable #"]; + 177 [label="Access variable R|/x|"]; + 178 [label="Access variable #"]; + 179 [label="Postponed enter to lambda"]; subgraph cluster_38 { color=blue - 191 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 193 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_39 { color=blue - 192 [label="Enter block"]; - 193 [label="Access variable R|/x|"]; - 194 [label="Type operator: (R|/x| as R|I1|)"]; + 194 [label="Enter block"]; 195 [label="Access variable R|/x|"]; - 196 [label="Smart cast: R|/x|"]; - 197 [label="Access variable #"]; - 198 [label="Function call: R|/n|()"]; - 199 [label="Exit block"]; + 196 [label="Type operator: (R|/x| as R|I1|)"]; + 197 [label="Access variable R|/x|"]; + 198 [label="Smart cast: R|/x|"]; + 199 [label="Access variable #"]; + 200 [label="Function call: R|/n|()"]; + 201 [label="Exit block"]; } - 200 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 202 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 179 [label="Postponed exit from lambda"]; - 180 [label="Postponed enter to lambda"]; + 181 [label="Postponed exit from lambda"]; + 182 [label="Postponed enter to lambda"]; subgraph cluster_40 { color=blue - 201 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 203 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_41 { color=blue - 202 [label="Enter block"]; - 203 [label="Access variable R|/x|"]; - 204 [label="Type operator: (R|/x| as R|I2|)"]; + 204 [label="Enter block"]; 205 [label="Access variable R|/x|"]; - 206 [label="Smart cast: R|/x|"]; - 207 [label="Access variable #"]; - 208 [label="Const: Int(123)"]; - 209 [label="Exit block"]; + 206 [label="Type operator: (R|/x| as R|I2|)"]; + 207 [label="Access variable R|/x|"]; + 208 [label="Smart cast: R|/x|"]; + 209 [label="Access variable #"]; + 210 [label="Const: Int(123)"]; + 211 [label="Exit block"]; } - 210 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 212 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 178 [label="Call arguments union" style="filled" fillcolor=yellow]; - 181 [label="Postponed exit from lambda"]; - 182 [label="Function call: R|/run2|(...)"]; - 183 [label="Access variable R|/x|"]; - 184 [label="Smart cast: R|/x|"]; - 185 [label="Access variable R|/I1.x|"]; - 186 [label="Access variable R|/x|"]; - 187 [label="Smart cast: R|/x|"]; - 188 [label="Access variable R|/I2.y|"]; - 189 [label="Exit block"]; + 180 [label="Call arguments union" style="filled" fillcolor=yellow]; + 183 [label="Postponed exit from lambda"]; + 184 [label="Function call: R|/run2|(...)"]; + 185 [label="Access variable R|/x|"]; + 186 [label="Smart cast: R|/x|"]; + 187 [label="Access variable R|/I1.x|"]; + 188 [label="Access variable R|/x|"]; + 189 [label="Smart cast: R|/x|"]; + 190 [label="Access variable R|/I2.y|"]; + 191 [label="Exit block"]; } - 190 [label="Exit function test4" style="filled" fillcolor=red]; + 192 [label="Exit function test4" style="filled" fillcolor=red]; } - 171 -> {172}; - 172 -> {173}; 173 -> {174}; 174 -> {175}; 175 -> {176}; 176 -> {177}; - 177 -> {191}; - 177 -> {179} [color=red]; - 177 -> {191} [style=dashed]; - 178 -> {182} [color=red]; - 179 -> {180}; - 180 -> {201}; - 180 -> {181} [color=red]; - 180 -> {201} [style=dashed]; - 181 -> {182} [color=green]; - 182 -> {183}; - 183 -> {184}; + 177 -> {178}; + 178 -> {179}; + 179 -> {193}; + 179 -> {181} [color=red]; + 179 -> {193} [style=dashed]; + 180 -> {184} [color=red]; + 181 -> {182}; + 182 -> {203}; + 182 -> {183} [color=red]; + 182 -> {203} [style=dashed]; + 183 -> {184} [color=green]; 184 -> {185}; 185 -> {186}; 186 -> {187}; 187 -> {188}; 188 -> {189}; 189 -> {190}; + 190 -> {191}; 191 -> {192}; - 192 -> {193}; 193 -> {194}; 194 -> {195}; 195 -> {196}; @@ -568,10 +570,10 @@ digraph flowFromTwoInplaceLambdas_kt { 197 -> {198}; 198 -> {199}; 199 -> {200}; - 200 -> {178} [color=red]; - 200 -> {179} [color=green]; + 200 -> {201}; 201 -> {202}; - 202 -> {203}; + 202 -> {180} [color=red]; + 202 -> {181} [color=green]; 203 -> {204}; 204 -> {205}; 205 -> {206}; @@ -579,7 +581,105 @@ digraph flowFromTwoInplaceLambdas_kt { 207 -> {208}; 208 -> {209}; 209 -> {210}; - 210 -> {178} [color=red]; - 210 -> {181} [color=green]; + 210 -> {211}; + 211 -> {212}; + 212 -> {180} [color=red]; + 212 -> {183} [color=green]; + + subgraph cluster_42 { + color=red + 213 [label="Enter function test5" style="filled" fillcolor=red]; + subgraph cluster_43 { + color=blue + 214 [label="Enter block"]; + 215 [label="Access variable R|/x|"]; + 216 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 217 [label="Access variable R|/p|"]; + 218 [label="Access variable #"]; + 219 [label="Postponed enter to lambda"]; + subgraph cluster_44 { + color=blue + 235 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_45 { + color=blue + 236 [label="Enter block"]; + 237 [label="Access variable R|/p|"]; + 238 [label="Type operator: (R|/p| as R|kotlin/Int|)"]; + 239 [label="Const: Int(123)"]; + 240 [label="Exit block"]; + } + 241 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 221 [label="Postponed exit from lambda"]; + 222 [label="Postponed enter to lambda"]; + subgraph cluster_46 { + color=blue + 242 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_47 { + color=blue + 243 [label="Enter block"]; + 244 [label="Access variable R|/q|"]; + 245 [label="Assignment: R|/p|"]; + 246 [label="Function call: R|/n|()"]; + 247 [label="Exit block"]; + } + 248 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 220 [label="Call arguments union" style="filled" fillcolor=yellow]; + 223 [label="Postponed exit from lambda"]; + 224 [label="Function call: R|/run2|(...)"]; + 225 [label="Access variable R|/p|"]; + 226 [label="Smart cast: R|/p|"]; + 227 [label="Access variable #"]; + 228 [label="Access variable R|/p|"]; + 229 [label="Smart cast: R|/p|"]; + 230 [label="Enter safe call"]; + 231 [label="Access variable R|kotlin/String.length|"]; + 232 [label="Exit safe call"]; + 233 [label="Exit block"]; + } + 234 [label="Exit function test5" style="filled" fillcolor=red]; + } + 213 -> {214}; + 214 -> {215}; + 215 -> {216}; + 216 -> {217}; + 217 -> {218}; + 218 -> {219}; + 219 -> {235}; + 219 -> {221} [color=red]; + 219 -> {235} [style=dashed]; + 220 -> {224} [color=red]; + 221 -> {222}; + 222 -> {242}; + 222 -> {223} [color=red]; + 222 -> {242} [style=dashed]; + 223 -> {224} [color=green]; + 224 -> {225}; + 225 -> {226}; + 226 -> {227}; + 227 -> {228}; + 228 -> {229}; + 229 -> {230 232}; + 230 -> {231}; + 231 -> {232}; + 232 -> {233}; + 233 -> {234}; + 235 -> {236}; + 236 -> {237}; + 237 -> {238}; + 238 -> {239}; + 239 -> {240}; + 240 -> {241}; + 241 -> {220} [color=red]; + 241 -> {221} [color=green]; + 242 -> {243}; + 243 -> {244}; + 244 -> {245}; + 245 -> {246}; + 246 -> {247}; + 247 -> {248}; + 248 -> {220} [color=red]; + 248 -> {223} [color=green]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt index 8c824c9b1a3..d40af10d969 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt @@ -61,8 +61,8 @@ FILE: flowFromTwoInplaceLambdas.kt ^ Int(123) } ) - R|/p|.# - R|/p|?.{ $subj$.R|kotlin/String.length| } + R|/p|.# + R|/p|?.{ $subj$.# } } public final fun test3(x: R|kotlin/Any?|): R|kotlin/Unit| { lvar p: R|kotlin/Any?| = R|/x| @@ -106,3 +106,18 @@ FILE: flowFromTwoInplaceLambdas.kt R|/x|.R|/I1.x| R|/x|.R|/I2.y| } + public final fun test5(x: R|kotlin/Any?|, q: R|kotlin/String?|): R|kotlin/Unit| { + lvar p: R|kotlin/Any?| = R|/x| + R|/p|.# + R|/run2|(run2@fun (): R|kotlin/Int?| { + (R|/p| as R|kotlin/Int|) + ^ Int(123) + } + , run2@fun (): R|kotlin/Int?| { + R|/p| = R|/q| + ^ R|/n|() + } + ) + R|/p|.# + R|/p|?.{ $subj$.R|kotlin/String.length| } + } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt index 3c94f0bc94c..94faaddb5f4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt @@ -38,8 +38,8 @@ fun test2(x: Any?) { var p: Any? = x p.length // Bad run2({ p = null; n() }, { p as String; 123 }) - p.length // Bad: p can be null - p?.length // OK: p is String | Nothing? = String? + p.length // Bad: p is Nothing? | (String & Nothing?) = Nothing? + p?.length // Technically OK because p is null, but what is "length"? } fun test3(x: Any?) { @@ -63,3 +63,11 @@ fun test4(x: Any?) { x.x // OK: x is I1 & I2 x.y // OK: x is I1 & I2 } + +fun test5(x: Any?, q: String?) { + var p: Any? = x + p.length // Bad + run2({ p as Int; 123 }, { p = q; n() }) + p.length // Bad: p is String? | (String? & Int) = String? + p?.length // OK: p is String? +} diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt index c52f0e1a18b..fc990d146a5 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt @@ -121,12 +121,15 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste val variables = flows.flatMapTo(mutableSetOf()) { it.approvedTypeStatements.keys + it.directAliasMap.keys } - commonAliases.keys val statements = variables.mapNotNull { variable -> val statement = if (allExecute) { - // All input flows execute in some order. If none of them reassign the variable, then - // *all* sets of statements are true; otherwise the assignments might have happened in - // an arbitrary order, so only one set of statements is true depending on which assignment - // happened last (and the flows that don't reassign may or may not have executed after that). - val byAssignment = flows.groupByTo(mutableMapOf()) { it.assignmentIndex[variable] ?: -1 }.values - or(byAssignment.map { flowSubset -> and(flowSubset.map { it.getTypeStatement(variable) }) }) + // All input flows execute in some order. If none of the flows reassign, i.e. the only key + // in `byAssignment` is `commonFlow`'s assignment index, then all statements are true. + // Otherwise, one of the assignments executed last, but we don't know which, and the flows + // that don't reassign should be ignored because they may have executed before or after that. + val byAssignment = flows.groupByTo(mutableMapOf()) { it.assignmentIndex[variable] ?: -1 } + if (byAssignment.size > 1) { + byAssignment.remove(commonFlow.assignmentIndex[variable] ?: -1) + } + or(byAssignment.values.map { flowSubset -> and(flowSubset.map { it.getTypeStatement(variable) }) }) } else { // One input flow executes - one set of statements is true, others might be false. or(flows.map { it.getTypeStatement(variable) })