From 3392e066dfa129c69faa94fbf5b82b83e3c340f5 Mon Sep 17 00:00:00 2001 From: pyos Date: Thu, 17 Nov 2022 00:05:43 +0100 Subject: [PATCH] FIR DFA: add more called-in-place tests --- .../resolve/cfg/flowFromInplaceLambda.dot | 1590 ++++++++++++----- .../resolve/cfg/flowFromInplaceLambda.fir.txt | 213 ++- .../resolve/cfg/flowFromInplaceLambda.kt | 196 +- .../resolve/cfg/flowFromInplaceLambda3.dot | 311 ++-- .../cfg/flowFromInplaceLambda3.fir.txt | 14 +- .../resolve/cfg/flowFromInplaceLambda3.kt | 10 +- .../resolve/cfg/flowFromTwoInplaceLambdas.dot | 188 ++ .../cfg/flowFromTwoInplaceLambdas.fir.txt | 29 + .../resolve/cfg/flowFromTwoInplaceLambdas.kt | 16 + 9 files changed, 1928 insertions(+), 639 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot index feb3cbcb778..856a537d7b1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot @@ -5,259 +5,303 @@ digraph flowFromInplaceLambda_kt { subgraph cluster_0 { color=red - 0 [label="Enter function takeInt" style="filled" fillcolor=red]; + 0 [label="Enter function unknown" style="filled" fillcolor=red]; subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Exit block"]; + 2 [label="Function call: R|/x|.R|SubstitutionOverride|()"]; + 3 [label="Jump: ^unknown R|/x|.R|SubstitutionOverride|()"]; + 4 [label="Stub" style="filled" fillcolor=gray]; + 5 [label="Exit block" style="filled" fillcolor=gray]; } - 3 [label="Exit function takeInt" style="filled" fillcolor=red]; + 6 [label="Exit function unknown" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; + 3 -> {6}; + 3 -> {4} [style=dotted]; + 4 -> {5} [style=dotted]; + 5 -> {6} [style=dotted]; subgraph cluster_2 { color=red - 4 [label="Enter function select" style="filled" fillcolor=red]; + 7 [label="Enter function atLeastOnce" style="filled" fillcolor=red]; subgraph cluster_3 { color=blue - 5 [label="Enter block"]; - 6 [label="Access variable R|/x|"]; - 7 [label="Const: Int(0)"]; - 8 [label="Function call: R|/x|.R|SubstitutionOverride|(...)"]; - 9 [label="Jump: ^select R|/x|.R|SubstitutionOverride|(Int(0))"]; - 10 [label="Stub" style="filled" fillcolor=gray]; - 11 [label="Exit block" style="filled" fillcolor=gray]; + 8 [label="Enter block"]; + 9 [label="Function call: R|/x|.R|SubstitutionOverride|()"]; + 10 [label="Jump: ^atLeastOnce R|/x|.R|SubstitutionOverride|()"]; + 11 [label="Stub" style="filled" fillcolor=gray]; + 12 [label="Exit block" style="filled" fillcolor=gray]; } - 12 [label="Exit function select" style="filled" fillcolor=red]; + 13 [label="Exit function atLeastOnce" style="filled" fillcolor=red]; } - 4 -> {5}; - 5 -> {6}; - 6 -> {7}; 7 -> {8}; 8 -> {9}; - 9 -> {12}; - 9 -> {10} [style=dotted]; + 9 -> {10}; + 10 -> {13}; 10 -> {11} [style=dotted]; 11 -> {12} [style=dotted]; + 12 -> {13} [style=dotted]; subgraph cluster_4 { color=red - 13 [label="Enter function id" style="filled" fillcolor=red]; + 14 [label="Enter function exactlyOnce" style="filled" fillcolor=red]; subgraph cluster_5 { color=blue - 14 [label="Enter block"]; - 15 [label="Access variable R|/x|"]; - 16 [label="Jump: ^id R|/x|"]; - 17 [label="Stub" style="filled" fillcolor=gray]; - 18 [label="Exit block" style="filled" fillcolor=gray]; + 15 [label="Enter block"]; + 16 [label="Function call: R|/x|.R|SubstitutionOverride|()"]; + 17 [label="Jump: ^exactlyOnce R|/x|.R|SubstitutionOverride|()"]; + 18 [label="Stub" style="filled" fillcolor=gray]; + 19 [label="Exit block" style="filled" fillcolor=gray]; } - 19 [label="Exit function id" style="filled" fillcolor=red]; + 20 [label="Exit function exactlyOnce" style="filled" fillcolor=red]; } - 13 -> {14}; 14 -> {15}; 15 -> {16}; - 16 -> {19}; - 16 -> {17} [style=dotted]; + 16 -> {17}; + 17 -> {20}; 17 -> {18} [style=dotted]; 18 -> {19} [style=dotted]; + 19 -> {20} [style=dotted]; subgraph cluster_6 { color=red - 20 [label="Enter function materialize" style="filled" fillcolor=red]; + 21 [label="Enter function atMostOnce" style="filled" fillcolor=red]; subgraph cluster_7 { color=blue - 21 [label="Enter block"]; - 22 [label="Const: Null(null)"]; - 23 [label="Check not null: Null(null)!!"]; - 24 [label="Stub" style="filled" fillcolor=gray]; - 25 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray]; - 26 [label="Stub" style="filled" fillcolor=gray]; - 27 [label="Exit block" style="filled" fillcolor=gray]; + 22 [label="Enter block"]; + 23 [label="Function call: R|/x|.R|SubstitutionOverride|()"]; + 24 [label="Jump: ^atMostOnce R|/x|.R|SubstitutionOverride|()"]; + 25 [label="Stub" style="filled" fillcolor=gray]; + 26 [label="Exit block" style="filled" fillcolor=gray]; } - 28 [label="Exit function materialize" style="filled" fillcolor=red]; + 27 [label="Exit function atMostOnce" style="filled" fillcolor=red]; } - 20 -> {21}; 21 -> {22}; 22 -> {23}; - 23 -> {28} [label=onUncaughtException]; - 23 -> {24} [style=dotted]; + 23 -> {24}; + 24 -> {27}; 24 -> {25} [style=dotted]; - 25 -> {28 26} [style=dotted]; + 25 -> {26} [style=dotted]; 26 -> {27} [style=dotted]; - 27 -> {28} [style=dotted]; subgraph cluster_8 { color=red - 29 [label="Enter function myRun" style="filled" fillcolor=red]; + 28 [label="Enter function noContract" style="filled" fillcolor=red]; subgraph cluster_9 { color=blue - 30 [label="Enter block"]; - 31 [label="Function call: R|/block|.R|SubstitutionOverride|()"]; - 32 [label="Jump: ^myRun R|/block|.R|SubstitutionOverride|()"]; - 33 [label="Stub" style="filled" fillcolor=gray]; - 34 [label="Exit block" style="filled" fillcolor=gray]; + 29 [label="Enter block"]; + 30 [label="Function call: R|/x|.R|SubstitutionOverride|()"]; + 31 [label="Jump: ^noContract R|/x|.R|SubstitutionOverride|()"]; + 32 [label="Stub" style="filled" fillcolor=gray]; + 33 [label="Exit block" style="filled" fillcolor=gray]; } - 35 [label="Exit function myRun" style="filled" fillcolor=red]; + 34 [label="Exit function noContract" style="filled" fillcolor=red]; } + 28 -> {29}; 29 -> {30}; 30 -> {31}; - 31 -> {32}; - 32 -> {35}; + 31 -> {34}; + 31 -> {32} [style=dotted]; 32 -> {33} [style=dotted]; 33 -> {34} [style=dotted]; - 34 -> {35} [style=dotted]; subgraph cluster_10 { color=red - 36 [label="Enter function test_1" style="filled" fillcolor=red]; + 35 [label="Enter function select" style="filled" fillcolor=red]; subgraph cluster_11 { color=blue - 37 [label="Enter block"]; - 38 [label="Postponed enter to lambda"]; - subgraph cluster_12 { - color=blue - 47 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_13 { - color=blue - 48 [label="Enter block"]; - 49 [label="Access variable R|/x|"]; - 50 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 51 [label="Exit block"]; - } - 52 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 39 [label="Call arguments union" style="filled" fillcolor=yellow]; - 40 [label="Postponed exit from lambda"]; - 41 [label="Function call: R|kotlin/run|(...)"]; - 42 [label="Access variable R|/x|"]; - 43 [label="Smart cast: R|/x|"]; - 44 [label="Function call: R|/takeInt|(...)"]; - 45 [label="Exit block"]; + 36 [label="Enter block"]; + 37 [label="Access variable R|/x|"]; + 38 [label="Const: Int(0)"]; + 39 [label="Function call: R|/x|.R|SubstitutionOverride|(...)"]; + 40 [label="Jump: ^select R|/x|.R|SubstitutionOverride|(Int(0))"]; + 41 [label="Stub" style="filled" fillcolor=gray]; + 42 [label="Exit block" style="filled" fillcolor=gray]; } - 46 [label="Exit function test_1" style="filled" fillcolor=red]; + 43 [label="Exit function select" style="filled" fillcolor=red]; } + 35 -> {36}; 36 -> {37}; 37 -> {38}; - 38 -> {47}; - 38 -> {40} [color=red]; - 38 -> {47} [style=dashed]; - 39 -> {41} [color=red]; - 40 -> {41} [color=green]; - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; + 38 -> {39}; + 39 -> {40}; + 40 -> {43}; + 40 -> {41} [style=dotted]; + 41 -> {42} [style=dotted]; + 42 -> {43} [style=dotted]; + + subgraph cluster_12 { + color=red + 44 [label="Enter function id" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 45 [label="Enter block"]; + 46 [label="Access variable R|/x|"]; + 47 [label="Jump: ^id R|/x|"]; + 48 [label="Stub" style="filled" fillcolor=gray]; + 49 [label="Exit block" style="filled" fillcolor=gray]; + } + 50 [label="Exit function id" style="filled" fillcolor=red]; + } 44 -> {45}; 45 -> {46}; - 47 -> {48}; - 48 -> {49}; - 49 -> {50}; - 50 -> {51}; - 51 -> {52}; - 52 -> {39} [color=red]; - 52 -> {40} [color=green]; + 46 -> {47}; + 47 -> {50}; + 47 -> {48} [style=dotted]; + 48 -> {49} [style=dotted]; + 49 -> {50} [style=dotted]; subgraph cluster_14 { color=red - 53 [label="Enter function test_2" style="filled" fillcolor=red]; + 51 [label="Enter function materialize" style="filled" fillcolor=red]; subgraph cluster_15 { color=blue - 54 [label="Enter block"]; - 55 [label="Postponed enter to lambda"]; - subgraph cluster_16 { - color=blue - 78 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_17 { - color=blue - 79 [label="Enter block"]; - 80 [label="Access variable R|/y|"]; - 81 [label="Function call: R|/y|.#()"]; - 82 [label="Access variable R|/x|"]; - 83 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 84 [label="Exit block"]; - } - 85 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 56 [label="Postponed exit from lambda"]; - 57 [label="Function call: R|kotlin/run|(...)"]; - 58 [label="Call arguments union" style="filled" fillcolor=yellow]; - 59 [label="Function call: R|/id|(...)"]; - 60 [label="Access variable R|/y|"]; - 61 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 52 [label="Enter block"]; + 53 [label="Const: Null(null)"]; + 54 [label="Check not null: Null(null)!!"]; + 55 [label="Stub" style="filled" fillcolor=gray]; + 56 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray]; + 57 [label="Stub" style="filled" fillcolor=gray]; + 58 [label="Exit block" style="filled" fillcolor=gray]; + } + 59 [label="Exit function materialize" style="filled" fillcolor=red]; + } + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {59} [label=onUncaughtException]; + 54 -> {55} [style=dotted]; + 55 -> {56} [style=dotted]; + 56 -> {59 57} [style=dotted]; + 57 -> {58} [style=dotted]; + 58 -> {59} [style=dotted]; + + subgraph cluster_16 { + color=red + 60 [label="Enter function basic" style="filled" fillcolor=red]; + subgraph cluster_17 { + color=blue + 61 [label="Enter block"]; 62 [label="Postponed enter to lambda"]; subgraph cluster_18 { color=blue - 86 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 71 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_19 { color=blue - 87 [label="Enter block"]; - 88 [label="Access variable R|/x|"]; - 89 [label="Smart cast: R|/x|"]; - 90 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; - 91 [label="Access variable R|/y|"]; - 92 [label="Smart cast: R|/y|"]; - 93 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; - 94 [label="Const: Int(1)"]; - 95 [label="Exit block"]; + 72 [label="Enter block"]; + 73 [label="Access variable R|/x|"]; + 74 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 75 [label="Exit block"]; } - 96 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 76 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 63 [label="Postponed exit from lambda"]; - 64 [label="Function call: R|kotlin/run|(...)"]; - 65 [label="Call arguments union" style="filled" fillcolor=yellow]; - 66 [label="Function call: R|/select|(...)"]; - 67 [label="Variable declaration: lval a: R|kotlin/Int|"]; - 68 [label="Access variable R|/x|"]; - 69 [label="Smart cast: R|/x|"]; - 70 [label="Function call: R|/takeInt|(...)"]; - 71 [label="Access variable R|/y|"]; - 72 [label="Smart cast: R|/y|"]; - 73 [label="Function call: R|/takeInt|(...)"]; - 74 [label="Access variable R|/a|"]; - 75 [label="Function call: R|/takeInt|(...)"]; - 76 [label="Exit block"]; + 63 [label="Call arguments union" style="filled" fillcolor=yellow]; + 64 [label="Postponed exit from lambda"]; + 65 [label="Function call: R|/exactlyOnce|(...)"]; + 66 [label="Access variable R|/x|"]; + 67 [label="Smart cast: R|/x|"]; + 68 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 69 [label="Exit block"]; } - 77 [label="Exit function test_2" style="filled" fillcolor=red]; + 70 [label="Exit function basic" style="filled" fillcolor=red]; } - 53 -> {54}; - 54 -> {55}; - 55 -> {78}; - 55 -> {56} [color=red]; - 55 -> {78} [style=dashed]; - 56 -> {57}; - 57 -> {58}; - 58 -> {59}; - 59 -> {60}; 60 -> {61}; 61 -> {62}; - 62 -> {86}; - 62 -> {63} [color=red]; - 62 -> {86} [style=dashed]; - 63 -> {64}; - 64 -> {65}; + 62 -> {71}; + 62 -> {64} [color=red]; + 62 -> {71} [style=dashed]; + 63 -> {65} [color=red]; + 64 -> {65} [color=green]; 65 -> {66}; 66 -> {67}; 67 -> {68}; 68 -> {69}; 69 -> {70}; - 70 -> {71}; 71 -> {72}; 72 -> {73}; 73 -> {74}; 74 -> {75}; 75 -> {76}; - 76 -> {77}; + 76 -> {63} [color=red]; + 76 -> {64} [color=green]; + + subgraph cluster_20 { + color=red + 77 [label="Enter function completedCallExactlyOnce" style="filled" fillcolor=red]; + subgraph cluster_21 { + color=blue + 78 [label="Enter block"]; + 79 [label="Postponed enter to lambda"]; + subgraph cluster_22 { + color=blue + 100 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_23 { + color=blue + 101 [label="Enter block"]; + 102 [label="Access variable R|/y|"]; + 103 [label="Function call: R|/y|.#()"]; + 104 [label="Access variable R|/x|"]; + 105 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 106 [label="Exit block"]; + } + 107 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 80 [label="Postponed exit from lambda"]; + 81 [label="Function call: R|/exactlyOnce|(...)"]; + 82 [label="Call arguments union" style="filled" fillcolor=yellow]; + 83 [label="Function call: R|/id|(...)"]; + 84 [label="Access variable R|/y|"]; + 85 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 86 [label="Postponed enter to lambda"]; + subgraph cluster_24 { + color=blue + 108 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_25 { + color=blue + 109 [label="Enter block"]; + 110 [label="Access variable R|/x|"]; + 111 [label="Smart cast: R|/x|"]; + 112 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 113 [label="Access variable R|/y|"]; + 114 [label="Smart cast: R|/y|"]; + 115 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 116 [label="Const: Int(1)"]; + 117 [label="Exit block"]; + } + 118 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 87 [label="Postponed exit from lambda"]; + 88 [label="Function call: R|/exactlyOnce|(...)"]; + 89 [label="Call arguments union" style="filled" fillcolor=yellow]; + 90 [label="Function call: R|/select|(...)"]; + 91 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 92 [label="Access variable R|/x|"]; + 93 [label="Smart cast: R|/x|"]; + 94 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 95 [label="Access variable R|/y|"]; + 96 [label="Smart cast: R|/y|"]; + 97 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 98 [label="Exit block"]; + } + 99 [label="Exit function completedCallExactlyOnce" style="filled" fillcolor=red]; + } + 77 -> {78}; 78 -> {79}; - 79 -> {80}; + 79 -> {100}; + 79 -> {80} [color=red]; + 79 -> {100} [style=dashed]; 80 -> {81}; 81 -> {82}; 82 -> {83}; 83 -> {84}; 84 -> {85}; - 85 -> {58} [color=red]; - 85 -> {56} [color=green]; - 86 -> {87}; + 85 -> {86}; + 86 -> {108}; + 86 -> {87} [color=red]; + 86 -> {108} [style=dashed]; 87 -> {88}; 88 -> {89}; 89 -> {90}; @@ -267,85 +311,18 @@ digraph flowFromInplaceLambda_kt { 93 -> {94}; 94 -> {95}; 95 -> {96}; - 96 -> {65} [color=red]; - 96 -> {63} [color=green]; - - subgraph cluster_20 { - color=red - 97 [label="Enter function test_3" style="filled" fillcolor=red]; - subgraph cluster_21 { - color=blue - 98 [label="Enter block"]; - 99 [label="Postponed enter to lambda"]; - subgraph cluster_22 { - color=blue - 119 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_23 { - color=blue - 120 [label="Enter block"]; - 121 [label="Access variable R|/y|"]; - 122 [label="Function call: R|/y|.#()"]; - 123 [label="Access variable R|/x|"]; - 124 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 125 [label="Function call: R|/materialize|()"]; - 126 [label="Exit block"]; - } - 127 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 100 [label="Postponed exit from lambda"]; - 101 [label="Function call: R|kotlin/run|(...)"]; - 102 [label="Function call: R|/id|(...)"]; - 103 [label="Postponed enter to lambda"]; - subgraph cluster_24 { - color=blue - 128 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_25 { - color=blue - 129 [label="Enter block"]; - 130 [label="Access variable R|/y|"]; - 131 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 132 [label="Access variable R|/x|"]; - 133 [label="Function call: R|/x|.#()"]; - 134 [label="Access variable R|/y|"]; - 135 [label="Smart cast: R|/y|"]; - 136 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; - 137 [label="Const: Int(1)"]; - 138 [label="Exit block"]; - } - 139 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 104 [label="Postponed exit from lambda"]; - 105 [label="Function call: R|kotlin/run|(...)"]; - 106 [label="Call arguments union" style="filled" fillcolor=yellow]; - 107 [label="Function call: R|/select|(...)"]; - 108 [label="Variable declaration: lval a: R|kotlin/Int|"]; - 109 [label="Access variable R|/x|"]; - 110 [label="Smart cast: R|/x|"]; - 111 [label="Function call: R|/takeInt|(...)"]; - 112 [label="Access variable R|/y|"]; - 113 [label="Smart cast: R|/y|"]; - 114 [label="Function call: R|/takeInt|(...)"]; - 115 [label="Access variable R|/a|"]; - 116 [label="Function call: R|/takeInt|(...)"]; - 117 [label="Exit block"]; - } - 118 [label="Exit function test_3" style="filled" fillcolor=red]; - } + 96 -> {97}; 97 -> {98}; 98 -> {99}; - 99 -> {119}; - 99 -> {100} [color=red]; - 99 -> {119} [style=dashed]; 100 -> {101}; 101 -> {102}; 102 -> {103}; - 103 -> {128}; - 103 -> {104} [color=red]; - 103 -> {128} [style=dashed]; + 103 -> {104}; 104 -> {105}; 105 -> {106}; 106 -> {107}; - 107 -> {108}; + 107 -> {82} [color=red]; + 107 -> {80} [color=green]; 108 -> {109}; 109 -> {110}; 110 -> {111}; @@ -356,17 +333,83 @@ digraph flowFromInplaceLambda_kt { 115 -> {116}; 116 -> {117}; 117 -> {118}; + 118 -> {89} [color=red]; + 118 -> {87} [color=green]; + + subgraph cluster_26 { + color=red + 119 [label="Enter function completedCallAtLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_27 { + color=blue + 120 [label="Enter block"]; + 121 [label="Postponed enter to lambda"]; + subgraph cluster_28 { + color=blue + 142 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_29 { + color=blue + 143 [label="Enter block"]; + 144 [label="Access variable R|/y|"]; + 145 [label="Function call: R|/y|.#()"]; + 146 [label="Access variable R|/x|"]; + 147 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 148 [label="Exit block"]; + } + 149 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 122 [label="Postponed exit from lambda"]; + 123 [label="Function call: R|/atLeastOnce|(...)"]; + 124 [label="Call arguments union" style="filled" fillcolor=yellow]; + 125 [label="Function call: R|/id|(...)"]; + 126 [label="Access variable R|/y|"]; + 127 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 128 [label="Postponed enter to lambda"]; + subgraph cluster_30 { + color=blue + 150 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_31 { + color=blue + 151 [label="Enter block"]; + 152 [label="Access variable R|/x|"]; + 153 [label="Smart cast: R|/x|"]; + 154 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 155 [label="Access variable R|/y|"]; + 156 [label="Smart cast: R|/y|"]; + 157 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 158 [label="Const: Int(1)"]; + 159 [label="Exit block"]; + } + 160 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 129 [label="Postponed exit from lambda"]; + 130 [label="Function call: R|/atLeastOnce|(...)"]; + 131 [label="Call arguments union" style="filled" fillcolor=yellow]; + 132 [label="Function call: R|/select|(...)"]; + 133 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 134 [label="Access variable R|/x|"]; + 135 [label="Smart cast: R|/x|"]; + 136 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 137 [label="Access variable R|/y|"]; + 138 [label="Smart cast: R|/y|"]; + 139 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 140 [label="Exit block"]; + } + 141 [label="Exit function completedCallAtLeastOnce" style="filled" fillcolor=red]; + } 119 -> {120}; 120 -> {121}; - 121 -> {122}; + 121 -> {142}; + 121 -> {122} [color=red]; + 121 -> {142} [style=dashed]; 122 -> {123}; 123 -> {124}; 124 -> {125}; 125 -> {126}; 126 -> {127}; - 127 -> {106} [color=red]; - 127 -> {100} [color=green]; - 128 -> {129}; + 127 -> {128}; + 128 -> {150}; + 128 -> {129} [color=red]; + 128 -> {150} [style=dashed]; 129 -> {130}; 130 -> {131}; 131 -> {132}; @@ -377,79 +420,18 @@ digraph flowFromInplaceLambda_kt { 136 -> {137}; 137 -> {138}; 138 -> {139}; - 139 -> {106} [color=red]; - 139 -> {104} [color=green]; - - subgraph cluster_26 { - color=red - 140 [label="Enter function test_4" style="filled" fillcolor=red]; - subgraph cluster_27 { - color=blue - 141 [label="Enter block"]; - 142 [label="Postponed enter to lambda"]; - subgraph cluster_28 { - color=blue - 162 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_29 { - color=blue - 163 [label="Enter block"]; - 164 [label="Access variable R|/y|"]; - 165 [label="Function call: R|/y|.#()"]; - 166 [label="Access variable R|/x|"]; - 167 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 168 [label="Exit block"]; - } - 169 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 143 [label="Postponed exit from lambda"]; - 144 [label="Function call: R|/myRun|(...)"]; - 145 [label="Function call: R|/id|(...)"]; - 146 [label="Access variable R|/y|"]; - 147 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 148 [label="Postponed enter to lambda"]; - subgraph cluster_30 { - color=blue - 170 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_31 { - color=blue - 171 [label="Enter block"]; - 172 [label="Access variable R|/x|"]; - 173 [label="Function call: R|/x|.#()"]; - 174 [label="Access variable R|/y|"]; - 175 [label="Smart cast: R|/y|"]; - 176 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; - 177 [label="Const: Int(1)"]; - 178 [label="Exit block"]; - } - 179 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 149 [label="Postponed exit from lambda"]; - 150 [label="Function call: R|/myRun|(...)"]; - 151 [label="Function call: R|/select|(...)"]; - 152 [label="Variable declaration: lval a: R|kotlin/Int|"]; - 153 [label="Access variable R|/x|"]; - 154 [label="Function call: #(...)"]; - 155 [label="Access variable R|/y|"]; - 156 [label="Smart cast: R|/y|"]; - 157 [label="Function call: R|/takeInt|(...)"]; - 158 [label="Access variable R|/a|"]; - 159 [label="Function call: R|/takeInt|(...)"]; - 160 [label="Exit block"]; - } - 161 [label="Exit function test_4" style="filled" fillcolor=red]; - } + 139 -> {140}; 140 -> {141}; - 141 -> {142}; - 142 -> {143 162}; - 142 -> {162} [style=dashed]; + 142 -> {143}; 143 -> {144}; 144 -> {145}; 145 -> {146}; 146 -> {147}; 147 -> {148}; - 148 -> {149 170}; - 148 -> {170} [style=dashed]; - 149 -> {150}; + 148 -> {149}; + 149 -> {124} [color=red]; + 149 -> {122} [color=green]; + 149 -> {142} [color=green style=dashed]; 150 -> {151}; 151 -> {152}; 152 -> {153}; @@ -460,14 +442,77 @@ digraph flowFromInplaceLambda_kt { 157 -> {158}; 158 -> {159}; 159 -> {160}; - 160 -> {161}; + 160 -> {131} [color=red]; + 160 -> {129} [color=green]; + 160 -> {150} [color=green style=dashed]; + + subgraph cluster_32 { + color=red + 161 [label="Enter function completedCallAtMostOnce" style="filled" fillcolor=red]; + subgraph cluster_33 { + color=blue + 162 [label="Enter block"]; + 163 [label="Postponed enter to lambda"]; + subgraph cluster_34 { + color=blue + 181 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_35 { + color=blue + 182 [label="Enter block"]; + 183 [label="Access variable R|/y|"]; + 184 [label="Function call: R|/y|.#()"]; + 185 [label="Access variable R|/x|"]; + 186 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 187 [label="Exit block"]; + } + 188 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 164 [label="Postponed exit from lambda"]; + 165 [label="Function call: R|/atMostOnce|(...)"]; + 166 [label="Function call: R|/id|(...)"]; + 167 [label="Access variable R|/y|"]; + 168 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 169 [label="Postponed enter to lambda"]; + subgraph cluster_36 { + color=blue + 189 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_37 { + color=blue + 190 [label="Enter block"]; + 191 [label="Access variable R|/x|"]; + 192 [label="Function call: R|/x|.#()"]; + 193 [label="Access variable R|/y|"]; + 194 [label="Smart cast: R|/y|"]; + 195 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 196 [label="Const: Int(1)"]; + 197 [label="Exit block"]; + } + 198 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 170 [label="Postponed exit from lambda"]; + 171 [label="Function call: R|/atMostOnce|(...)"]; + 172 [label="Function call: R|/select|(...)"]; + 173 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 174 [label="Access variable R|/x|"]; + 175 [label="Function call: R|/x|.#()"]; + 176 [label="Access variable R|/y|"]; + 177 [label="Smart cast: R|/y|"]; + 178 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 179 [label="Exit block"]; + } + 180 [label="Exit function completedCallAtMostOnce" style="filled" fillcolor=red]; + } + 161 -> {162}; 162 -> {163}; - 163 -> {164}; + 163 -> {164 181}; + 163 -> {181} [style=dashed]; 164 -> {165}; 165 -> {166}; 166 -> {167}; 167 -> {168}; 168 -> {169}; + 169 -> {170 189}; + 169 -> {189} [style=dashed]; 170 -> {171}; 171 -> {172}; 172 -> {173}; @@ -477,141 +522,888 @@ digraph flowFromInplaceLambda_kt { 176 -> {177}; 177 -> {178}; 178 -> {179}; - - subgraph cluster_32 { - color=red - 180 [label="Enter function test_5" style="filled" fillcolor=red]; - subgraph cluster_33 { - color=blue - 181 [label="Enter block"]; - 182 [label="Postponed enter to lambda"]; - subgraph cluster_34 { - color=blue - 195 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_35 { - color=blue - 196 [label="Enter block"]; - 197 [label="Function call: R|/materialize|()"]; - 198 [label="Exit block"]; - } - 199 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 183 [label="Postponed exit from lambda"]; - 184 [label="Function call: R|kotlin/run|(...)"]; - 185 [label="Postponed enter to lambda"]; - subgraph cluster_36 { - color=blue - 200 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_37 { - color=blue - 201 [label="Enter block"]; - 202 [label="Function call: R|/materialize|()"]; - 203 [label="Exit block"]; - } - 204 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 186 [label="Postponed exit from lambda"]; - 187 [label="Function call: R|kotlin/run|(...)"]; - 188 [label="Call arguments union" style="filled" fillcolor=yellow]; - 189 [label="Function call: R|/select|(...)"]; - 190 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 191 [label="Access variable R|/x|"]; - 192 [label="Function call: R|/takeInt|(...)"]; - 193 [label="Exit block"]; - } - 194 [label="Exit function test_5" style="filled" fillcolor=red]; - } - 180 -> {181}; - 181 -> {182}; - 182 -> {195}; - 182 -> {183} [color=red]; - 182 -> {195} [style=dashed]; + 179 -> {180}; + 181 -> {188 182}; + 182 -> {183}; 183 -> {184}; 184 -> {185}; - 185 -> {200}; - 185 -> {186} [color=red]; - 185 -> {200} [style=dashed]; + 185 -> {186}; 186 -> {187}; 187 -> {188}; - 188 -> {189}; - 189 -> {190}; + 188 -> {164}; + 189 -> {198 190}; 190 -> {191}; 191 -> {192}; 192 -> {193}; 193 -> {194}; + 194 -> {195}; 195 -> {196}; 196 -> {197}; 197 -> {198}; - 198 -> {199}; - 199 -> {188} [color=red]; - 199 -> {183} [color=green]; - 200 -> {201}; - 201 -> {202}; - 202 -> {203}; - 203 -> {204}; - 204 -> {188} [color=red]; - 204 -> {186} [color=green]; + 198 -> {170}; subgraph cluster_38 { color=red - 205 [label="Enter function test_6" style="filled" fillcolor=red]; + 199 [label="Enter function completedCallUnknown" style="filled" fillcolor=red]; subgraph cluster_39 { color=blue - 206 [label="Enter block"]; - 207 [label="Postponed enter to lambda"]; + 200 [label="Enter block"]; + 201 [label="Postponed enter to lambda"]; subgraph cluster_40 { color=blue - 214 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 219 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_41 { color=blue - 215 [label="Enter block"]; - 216 [label="Postponed enter to lambda"]; - subgraph cluster_42 { - color=blue - 221 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_43 { - color=blue - 222 [label="Enter block"]; - 223 [label="Function call: R|/materialize|()"]; - 224 [label="Exit block"]; - } - 225 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 217 [label="Postponed exit from lambda"]; - 218 [label="Function call: R|kotlin/run|(...)"]; - 219 [label="Exit block"]; + 220 [label="Enter block"]; + 221 [label="Access variable R|/y|"]; + 222 [label="Function call: R|/y|.#()"]; + 223 [label="Access variable R|/x|"]; + 224 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 225 [label="Exit block"]; } - 220 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 226 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 202 [label="Postponed exit from lambda"]; + 203 [label="Function call: R|/unknown|(...)"]; + 204 [label="Function call: R|/id|(...)"]; + 205 [label="Access variable R|/y|"]; + 206 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 207 [label="Postponed enter to lambda"]; + subgraph cluster_42 { + color=blue + 227 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_43 { + color=blue + 228 [label="Enter block"]; + 229 [label="Access variable R|/x|"]; + 230 [label="Function call: R|/x|.#()"]; + 231 [label="Access variable R|/y|"]; + 232 [label="Smart cast: R|/y|"]; + 233 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 234 [label="Const: Int(1)"]; + 235 [label="Exit block"]; + } + 236 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 208 [label="Postponed exit from lambda"]; - 209 [label="Function call: R|/myRun|(...)"]; - 210 [label="Function call: R|/id|(...)"]; - 211 [label="Variable declaration: lval x: R|kotlin/String|"]; - 212 [label="Exit block"]; + 209 [label="Function call: R|/unknown|(...)"]; + 210 [label="Function call: R|/select|(...)"]; + 211 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 212 [label="Access variable R|/x|"]; + 213 [label="Function call: R|/x|.#()"]; + 214 [label="Access variable R|/y|"]; + 215 [label="Smart cast: R|/y|"]; + 216 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 217 [label="Exit block"]; } - 213 [label="Exit function test_6" style="filled" fillcolor=red]; + 218 [label="Exit function completedCallUnknown" style="filled" fillcolor=red]; } + 199 -> {200}; + 200 -> {201}; + 201 -> {202 219}; + 201 -> {219} [style=dashed]; + 202 -> {203}; + 203 -> {204}; + 204 -> {205}; 205 -> {206}; 206 -> {207}; - 207 -> {208 214}; - 207 -> {214} [style=dashed]; + 207 -> {208 227}; + 207 -> {227} [style=dashed]; 208 -> {209}; 209 -> {210}; 210 -> {211}; 211 -> {212}; 212 -> {213}; + 213 -> {214}; 214 -> {215}; 215 -> {216}; - 216 -> {221}; - 216 -> {217} [color=red]; - 216 -> {221} [style=dashed]; + 216 -> {217}; 217 -> {218}; - 218 -> {219}; - 219 -> {220}; + 219 -> {226 220}; + 220 -> {221}; 221 -> {222}; 222 -> {223}; 223 -> {224}; 224 -> {225}; - 225 -> {217} [color=green]; + 225 -> {226}; + 226 -> {202}; + 226 -> {219} [color=green style=dashed]; + 227 -> {236 228}; + 228 -> {229}; + 229 -> {230}; + 230 -> {231}; + 231 -> {232}; + 232 -> {233}; + 233 -> {234}; + 234 -> {235}; + 235 -> {236}; + 236 -> {208}; + 236 -> {227} [color=green style=dashed]; + + subgraph cluster_44 { + color=red + 237 [label="Enter function completedCallNoContract" style="filled" fillcolor=red]; + subgraph cluster_45 { + color=blue + 238 [label="Enter block"]; + 239 [label="Postponed enter to lambda"]; + subgraph cluster_46 { + color=blue + 257 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_47 { + color=blue + 258 [label="Enter block"]; + 259 [label="Access variable R|/y|"]; + 260 [label="Function call: R|/y|.#()"]; + 261 [label="Access variable R|/x|"]; + 262 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 263 [label="Exit block"]; + } + 264 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 240 [label="Postponed exit from lambda"]; + 241 [label="Function call: R|/noContract|(...)"]; + 242 [label="Function call: R|/id|(...)"]; + 243 [label="Access variable R|/y|"]; + 244 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 245 [label="Postponed enter to lambda"]; + subgraph cluster_48 { + color=blue + 265 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_49 { + color=blue + 266 [label="Enter block"]; + 267 [label="Access variable R|/x|"]; + 268 [label="Function call: R|/x|.#()"]; + 269 [label="Access variable R|/y|"]; + 270 [label="Smart cast: R|/y|"]; + 271 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 272 [label="Const: Int(1)"]; + 273 [label="Exit block"]; + } + 274 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 246 [label="Postponed exit from lambda"]; + 247 [label="Function call: R|/noContract|(...)"]; + 248 [label="Function call: R|/select|(...)"]; + 249 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 250 [label="Access variable R|/x|"]; + 251 [label="Function call: R|/x|.#()"]; + 252 [label="Access variable R|/y|"]; + 253 [label="Smart cast: R|/y|"]; + 254 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 255 [label="Exit block"]; + } + 256 [label="Exit function completedCallNoContract" style="filled" fillcolor=red]; + } + 237 -> {238}; + 238 -> {239}; + 239 -> {240 257}; + 239 -> {257} [style=dashed]; + 240 -> {241}; + 241 -> {242}; + 242 -> {243}; + 243 -> {244}; + 244 -> {245}; + 245 -> {246 265}; + 245 -> {265} [style=dashed]; + 246 -> {247}; + 247 -> {248}; + 248 -> {249}; + 249 -> {250}; + 250 -> {251}; + 251 -> {252}; + 252 -> {253}; + 253 -> {254}; + 254 -> {255}; + 255 -> {256}; + 257 -> {258}; + 258 -> {259}; + 259 -> {260}; + 260 -> {261}; + 261 -> {262}; + 262 -> {263}; + 263 -> {264}; + 265 -> {266}; + 266 -> {267}; + 267 -> {268}; + 268 -> {269}; + 269 -> {270}; + 270 -> {271}; + 271 -> {272}; + 272 -> {273}; + 273 -> {274}; + + subgraph cluster_50 { + color=red + 275 [label="Enter function incompleteCallExactlyOnce" style="filled" fillcolor=red]; + subgraph cluster_51 { + color=blue + 276 [label="Enter block"]; + 277 [label="Postponed enter to lambda"]; + subgraph cluster_52 { + color=blue + 295 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_53 { + color=blue + 296 [label="Enter block"]; + 297 [label="Access variable R|/x|"]; + 298 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 299 [label="Access variable R|/y|"]; + 300 [label="Function call: R|/y|.#()"]; + 301 [label="Access variable R|/x|"]; + 302 [label="Smart cast: R|/x|"]; + 303 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 304 [label="Function call: R|/materialize|()"]; + 305 [label="Exit block"]; + } + 306 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 278 [label="Postponed exit from lambda"]; + 279 [label="Function call: R|/exactlyOnce|(...)"]; + 280 [label="Function call: R|/id|(...)"]; + 281 [label="Postponed enter to lambda"]; + subgraph cluster_54 { + color=blue + 307 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_55 { + color=blue + 308 [label="Enter block"]; + 309 [label="Access variable R|/y|"]; + 310 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 311 [label="Access variable R|/x|"]; + 312 [label="Function call: R|/x|.#()"]; + 313 [label="Access variable R|/y|"]; + 314 [label="Smart cast: R|/y|"]; + 315 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 316 [label="Const: Int(1)"]; + 317 [label="Exit block"]; + } + 318 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 282 [label="Postponed exit from lambda"]; + 283 [label="Function call: R|/exactlyOnce|(...)"]; + 284 [label="Call arguments union" style="filled" fillcolor=yellow]; + 285 [label="Function call: R|/select|(...)"]; + 286 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 287 [label="Access variable R|/x|"]; + 288 [label="Smart cast: R|/x|"]; + 289 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 290 [label="Access variable R|/y|"]; + 291 [label="Smart cast: R|/y|"]; + 292 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 293 [label="Exit block"]; + } + 294 [label="Exit function incompleteCallExactlyOnce" style="filled" fillcolor=red]; + } + 275 -> {276}; + 276 -> {277}; + 277 -> {295}; + 277 -> {278} [color=red]; + 277 -> {295} [style=dashed]; + 278 -> {279}; + 279 -> {280}; + 280 -> {281}; + 281 -> {307}; + 281 -> {282} [color=red]; + 281 -> {307} [style=dashed]; + 282 -> {283}; + 283 -> {284}; + 284 -> {285}; + 285 -> {286}; + 286 -> {287}; + 287 -> {288}; + 288 -> {289}; + 289 -> {290}; + 290 -> {291}; + 291 -> {292}; + 292 -> {293}; + 293 -> {294}; + 295 -> {296}; + 296 -> {297}; + 297 -> {298}; + 298 -> {299}; + 299 -> {300}; + 300 -> {301}; + 301 -> {302}; + 302 -> {303}; + 303 -> {304}; + 304 -> {305}; + 305 -> {306}; + 306 -> {284} [color=red]; + 306 -> {278} [color=green]; + 307 -> {308}; + 308 -> {309}; + 309 -> {310}; + 310 -> {311}; + 311 -> {312}; + 312 -> {313}; + 313 -> {314}; + 314 -> {315}; + 315 -> {316}; + 316 -> {317}; + 317 -> {318}; + 318 -> {284} [color=red]; + 318 -> {282} [color=green]; + + subgraph cluster_56 { + color=red + 319 [label="Enter function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_57 { + color=blue + 320 [label="Enter block"]; + 321 [label="Postponed enter to lambda"]; + subgraph cluster_58 { + color=blue + 339 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_59 { + color=blue + 340 [label="Enter block"]; + 341 [label="Access variable R|/x|"]; + 342 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 343 [label="Access variable R|/y|"]; + 344 [label="Function call: R|/y|.#()"]; + 345 [label="Access variable R|/x|"]; + 346 [label="Smart cast: R|/x|"]; + 347 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 348 [label="Function call: R|/materialize|()"]; + 349 [label="Exit block"]; + } + 350 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 322 [label="Postponed exit from lambda"]; + 323 [label="Function call: R|/atLeastOnce|(...)"]; + 324 [label="Function call: R|/id|(...)"]; + 325 [label="Postponed enter to lambda"]; + subgraph cluster_60 { + color=blue + 351 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_61 { + color=blue + 352 [label="Enter block"]; + 353 [label="Access variable R|/y|"]; + 354 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 355 [label="Access variable R|/x|"]; + 356 [label="Function call: R|/x|.#()"]; + 357 [label="Access variable R|/y|"]; + 358 [label="Smart cast: R|/y|"]; + 359 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 360 [label="Const: Int(1)"]; + 361 [label="Exit block"]; + } + 362 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 326 [label="Postponed exit from lambda"]; + 327 [label="Function call: R|/atLeastOnce|(...)"]; + 328 [label="Call arguments union" style="filled" fillcolor=yellow]; + 329 [label="Function call: R|/select|(...)"]; + 330 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 331 [label="Access variable R|/x|"]; + 332 [label="Smart cast: R|/x|"]; + 333 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 334 [label="Access variable R|/y|"]; + 335 [label="Smart cast: R|/y|"]; + 336 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 337 [label="Exit block"]; + } + 338 [label="Exit function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; + } + 319 -> {320}; + 320 -> {321}; + 321 -> {339}; + 321 -> {322} [color=red]; + 321 -> {339} [style=dashed]; + 322 -> {323}; + 323 -> {324}; + 324 -> {325}; + 325 -> {351}; + 325 -> {326} [color=red]; + 325 -> {351} [style=dashed]; + 326 -> {327}; + 327 -> {328}; + 328 -> {329}; + 329 -> {330}; + 330 -> {331}; + 331 -> {332}; + 332 -> {333}; + 333 -> {334}; + 334 -> {335}; + 335 -> {336}; + 336 -> {337}; + 337 -> {338}; + 339 -> {340}; + 340 -> {341}; + 341 -> {342}; + 342 -> {343}; + 343 -> {344}; + 344 -> {345}; + 345 -> {346}; + 346 -> {347}; + 347 -> {348}; + 348 -> {349}; + 349 -> {350}; + 350 -> {328} [color=red]; + 350 -> {322} [color=green]; + 350 -> {339} [color=green style=dashed]; + 351 -> {352}; + 352 -> {353}; + 353 -> {354}; + 354 -> {355}; + 355 -> {356}; + 356 -> {357}; + 357 -> {358}; + 358 -> {359}; + 359 -> {360}; + 360 -> {361}; + 361 -> {362}; + 362 -> {328} [color=red]; + 362 -> {326} [color=green]; + 362 -> {351} [color=green style=dashed]; + + subgraph cluster_62 { + color=red + 363 [label="Enter function incompleteCallAtMostOnce" style="filled" fillcolor=red]; + subgraph cluster_63 { + color=blue + 364 [label="Enter block"]; + 365 [label="Postponed enter to lambda"]; + subgraph cluster_64 { + color=blue + 380 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_65 { + color=blue + 381 [label="Enter block"]; + 382 [label="Access variable R|/x|"]; + 383 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 384 [label="Access variable R|/y|"]; + 385 [label="Function call: R|/y|.#()"]; + 386 [label="Access variable R|/x|"]; + 387 [label="Smart cast: R|/x|"]; + 388 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 389 [label="Function call: R|/materialize|()"]; + 390 [label="Exit block"]; + } + 391 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 366 [label="Postponed exit from lambda"]; + 367 [label="Function call: R|/atMostOnce|(...)"]; + 368 [label="Function call: R|/id|(...)"]; + 369 [label="Postponed enter to lambda"]; + subgraph cluster_66 { + color=blue + 392 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_67 { + color=blue + 393 [label="Enter block"]; + 394 [label="Access variable R|/y|"]; + 395 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 396 [label="Access variable R|/x|"]; + 397 [label="Function call: R|/x|.#()"]; + 398 [label="Access variable R|/y|"]; + 399 [label="Smart cast: R|/y|"]; + 400 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 401 [label="Const: Int(1)"]; + 402 [label="Exit block"]; + } + 403 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 370 [label="Postponed exit from lambda"]; + 371 [label="Function call: R|/atMostOnce|(...)"]; + 372 [label="Function call: R|/select|(...)"]; + 373 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 374 [label="Access variable R|/x|"]; + 375 [label="Function call: R|/x|.#()"]; + 376 [label="Access variable R|/y|"]; + 377 [label="Function call: R|/y|.#()"]; + 378 [label="Exit block"]; + } + 379 [label="Exit function incompleteCallAtMostOnce" style="filled" fillcolor=red]; + } + 363 -> {364}; + 364 -> {365}; + 365 -> {366 380}; + 365 -> {380} [style=dashed]; + 366 -> {367}; + 367 -> {368}; + 368 -> {369}; + 369 -> {370 392}; + 369 -> {392} [style=dashed]; + 370 -> {371}; + 371 -> {372}; + 372 -> {373}; + 373 -> {374}; + 374 -> {375}; + 375 -> {376}; + 376 -> {377}; + 377 -> {378}; + 378 -> {379}; + 380 -> {391 381}; + 381 -> {382}; + 382 -> {383}; + 383 -> {384}; + 384 -> {385}; + 385 -> {386}; + 386 -> {387}; + 387 -> {388}; + 388 -> {389}; + 389 -> {390}; + 390 -> {391}; + 391 -> {366}; + 392 -> {403 393}; + 393 -> {394}; + 394 -> {395}; + 395 -> {396}; + 396 -> {397}; + 397 -> {398}; + 398 -> {399}; + 399 -> {400}; + 400 -> {401}; + 401 -> {402}; + 402 -> {403}; + 403 -> {370}; + + subgraph cluster_68 { + color=red + 404 [label="Enter function incompleteCallUnknown" style="filled" fillcolor=red]; + subgraph cluster_69 { + color=blue + 405 [label="Enter block"]; + 406 [label="Postponed enter to lambda"]; + subgraph cluster_70 { + color=blue + 421 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_71 { + color=blue + 422 [label="Enter block"]; + 423 [label="Access variable R|/x|"]; + 424 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 425 [label="Access variable R|/y|"]; + 426 [label="Function call: R|/y|.#()"]; + 427 [label="Access variable R|/x|"]; + 428 [label="Smart cast: R|/x|"]; + 429 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 430 [label="Function call: R|/materialize|()"]; + 431 [label="Exit block"]; + } + 432 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 407 [label="Postponed exit from lambda"]; + 408 [label="Function call: R|/unknown|(...)"]; + 409 [label="Function call: R|/id|(...)"]; + 410 [label="Postponed enter to lambda"]; + subgraph cluster_72 { + color=blue + 433 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_73 { + color=blue + 434 [label="Enter block"]; + 435 [label="Access variable R|/y|"]; + 436 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 437 [label="Access variable R|/x|"]; + 438 [label="Function call: R|/x|.#()"]; + 439 [label="Access variable R|/y|"]; + 440 [label="Smart cast: R|/y|"]; + 441 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 442 [label="Const: Int(1)"]; + 443 [label="Exit block"]; + } + 444 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 411 [label="Postponed exit from lambda"]; + 412 [label="Function call: R|/unknown|(...)"]; + 413 [label="Function call: R|/select|(...)"]; + 414 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 415 [label="Access variable R|/x|"]; + 416 [label="Function call: R|/x|.#()"]; + 417 [label="Access variable R|/y|"]; + 418 [label="Function call: R|/y|.#()"]; + 419 [label="Exit block"]; + } + 420 [label="Exit function incompleteCallUnknown" style="filled" fillcolor=red]; + } + 404 -> {405}; + 405 -> {406}; + 406 -> {407 421}; + 406 -> {421} [style=dashed]; + 407 -> {408}; + 408 -> {409}; + 409 -> {410}; + 410 -> {411 433}; + 410 -> {433} [style=dashed]; + 411 -> {412}; + 412 -> {413}; + 413 -> {414}; + 414 -> {415}; + 415 -> {416}; + 416 -> {417}; + 417 -> {418}; + 418 -> {419}; + 419 -> {420}; + 421 -> {432 422}; + 422 -> {423}; + 423 -> {424}; + 424 -> {425}; + 425 -> {426}; + 426 -> {427}; + 427 -> {428}; + 428 -> {429}; + 429 -> {430}; + 430 -> {431}; + 431 -> {432}; + 432 -> {407}; + 432 -> {421} [color=green style=dashed]; + 433 -> {444 434}; + 434 -> {435}; + 435 -> {436}; + 436 -> {437}; + 437 -> {438}; + 438 -> {439}; + 439 -> {440}; + 440 -> {441}; + 441 -> {442}; + 442 -> {443}; + 443 -> {444}; + 444 -> {411}; + 444 -> {433} [color=green style=dashed]; + + subgraph cluster_74 { + color=red + 445 [label="Enter function incompleteCallNoContract" style="filled" fillcolor=red]; + subgraph cluster_75 { + color=blue + 446 [label="Enter block"]; + 447 [label="Postponed enter to lambda"]; + subgraph cluster_76 { + color=blue + 462 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_77 { + color=blue + 463 [label="Enter block"]; + 464 [label="Access variable R|/x|"]; + 465 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 466 [label="Access variable R|/y|"]; + 467 [label="Function call: R|/y|.#()"]; + 468 [label="Access variable R|/x|"]; + 469 [label="Smart cast: R|/x|"]; + 470 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 471 [label="Function call: R|/materialize|()"]; + 472 [label="Exit block"]; + } + 473 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 448 [label="Postponed exit from lambda"]; + 449 [label="Function call: R|/noContract|(...)"]; + 450 [label="Function call: R|/id|(...)"]; + 451 [label="Postponed enter to lambda"]; + subgraph cluster_78 { + color=blue + 474 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_79 { + color=blue + 475 [label="Enter block"]; + 476 [label="Access variable R|/y|"]; + 477 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 478 [label="Access variable R|/x|"]; + 479 [label="Function call: R|/x|.#()"]; + 480 [label="Access variable R|/y|"]; + 481 [label="Smart cast: R|/y|"]; + 482 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 483 [label="Const: Int(1)"]; + 484 [label="Exit block"]; + } + 485 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 452 [label="Postponed exit from lambda"]; + 453 [label="Function call: R|/noContract|(...)"]; + 454 [label="Function call: R|/select|(...)"]; + 455 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()"]; + 456 [label="Access variable R|/x|"]; + 457 [label="Function call: R|/x|.#()"]; + 458 [label="Access variable R|/y|"]; + 459 [label="Function call: R|/y|.#()"]; + 460 [label="Exit block"]; + } + 461 [label="Exit function incompleteCallNoContract" style="filled" fillcolor=red]; + } + 445 -> {446}; + 446 -> {447}; + 447 -> {448 462}; + 447 -> {462} [style=dashed]; + 448 -> {449}; + 449 -> {450}; + 450 -> {451}; + 451 -> {452 474}; + 451 -> {474} [style=dashed]; + 452 -> {453}; + 453 -> {454}; + 454 -> {455}; + 455 -> {456}; + 456 -> {457}; + 457 -> {458}; + 458 -> {459}; + 459 -> {460}; + 460 -> {461}; + 462 -> {463}; + 463 -> {464}; + 464 -> {465}; + 465 -> {466}; + 466 -> {467}; + 467 -> {468}; + 468 -> {469}; + 469 -> {470}; + 470 -> {471}; + 471 -> {472}; + 472 -> {473}; + 474 -> {475}; + 475 -> {476}; + 476 -> {477}; + 477 -> {478}; + 478 -> {479}; + 479 -> {480}; + 480 -> {481}; + 481 -> {482}; + 482 -> {483}; + 483 -> {484}; + 484 -> {485}; + + subgraph cluster_80 { + color=red + 486 [label="Enter function expectedType" style="filled" fillcolor=red]; + subgraph cluster_81 { + color=blue + 487 [label="Enter block"]; + 488 [label="Postponed enter to lambda"]; + subgraph cluster_82 { + color=blue + 501 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_83 { + color=blue + 502 [label="Enter block"]; + 503 [label="Function call: R|/materialize|()"]; + 504 [label="Exit block"]; + } + 505 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 489 [label="Postponed exit from lambda"]; + 490 [label="Function call: R|kotlin/run|(...)"]; + 491 [label="Postponed enter to lambda"]; + subgraph cluster_84 { + color=blue + 506 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_85 { + color=blue + 507 [label="Enter block"]; + 508 [label="Function call: R|/materialize|()"]; + 509 [label="Exit block"]; + } + 510 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 492 [label="Postponed exit from lambda"]; + 493 [label="Function call: R|kotlin/run|(...)"]; + 494 [label="Call arguments union" style="filled" fillcolor=yellow]; + 495 [label="Function call: R|/select|(...)"]; + 496 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 497 [label="Access variable R|/x|"]; + 498 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 499 [label="Exit block"]; + } + 500 [label="Exit function expectedType" style="filled" fillcolor=red]; + } + 486 -> {487}; + 487 -> {488}; + 488 -> {501}; + 488 -> {489} [color=red]; + 488 -> {501} [style=dashed]; + 489 -> {490}; + 490 -> {491}; + 491 -> {506}; + 491 -> {492} [color=red]; + 491 -> {506} [style=dashed]; + 492 -> {493}; + 493 -> {494}; + 494 -> {495}; + 495 -> {496}; + 496 -> {497}; + 497 -> {498}; + 498 -> {499}; + 499 -> {500}; + 501 -> {502}; + 502 -> {503}; + 503 -> {504}; + 504 -> {505}; + 505 -> {494} [color=red]; + 505 -> {489} [color=green]; + 506 -> {507}; + 507 -> {508}; + 508 -> {509}; + 509 -> {510}; + 510 -> {494} [color=red]; + 510 -> {492} [color=green]; + + subgraph cluster_86 { + color=red + 511 [label="Enter function expectedTypeNested" style="filled" fillcolor=red]; + subgraph cluster_87 { + color=blue + 512 [label="Enter block"]; + 513 [label="Postponed enter to lambda"]; + subgraph cluster_88 { + color=blue + 522 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_89 { + color=blue + 523 [label="Enter block"]; + 524 [label="Postponed enter to lambda"]; + subgraph cluster_90 { + color=blue + 529 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_91 { + color=blue + 530 [label="Enter block"]; + 531 [label="Function call: R|/materialize|()"]; + 532 [label="Exit block"]; + } + 533 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 525 [label="Postponed exit from lambda"]; + 526 [label="Function call: R|kotlin/run|(...)"]; + 527 [label="Exit block"]; + } + 528 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 514 [label="Postponed exit from lambda"]; + 515 [label="Function call: R|/noContract|(...)"]; + 516 [label="Function call: R|/id|(...)"]; + 517 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 518 [label="Access variable R|/x|"]; + 519 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 520 [label="Exit block"]; + } + 521 [label="Exit function expectedTypeNested" style="filled" fillcolor=red]; + } + 511 -> {512}; + 512 -> {513}; + 513 -> {514 522}; + 513 -> {522} [style=dashed]; + 514 -> {515}; + 515 -> {516}; + 516 -> {517}; + 517 -> {518}; + 518 -> {519}; + 519 -> {520}; + 520 -> {521}; + 522 -> {523}; + 523 -> {524}; + 524 -> {529}; + 524 -> {525} [color=red]; + 524 -> {529} [style=dashed]; + 525 -> {526}; + 526 -> {527}; + 527 -> {528}; + 529 -> {530}; + 530 -> {531}; + 531 -> {532}; + 532 -> {533}; + 533 -> {525} [color=green]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt index 2f771773521..3b086a96dd4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt @@ -1,5 +1,42 @@ FILE: flowFromInplaceLambda.kt - public final fun takeInt(x: R|kotlin/Int|): R|kotlin/Unit| { + public final fun unknown(x: R|() -> T|): R|T| + [R|Contract description] + < + CallsInPlace(x, UNKNOWN) + > + { + [StubStatement] + ^unknown R|/x|.R|SubstitutionOverride|() + } + public final fun atLeastOnce(x: R|() -> T|): R|T| + [R|Contract description] + < + CallsInPlace(x, AT_LEAST_ONCE) + > + { + [StubStatement] + ^atLeastOnce R|/x|.R|SubstitutionOverride|() + } + public final fun exactlyOnce(x: R|() -> T|): R|T| + [R|Contract description] + < + CallsInPlace(x, EXACTLY_ONCE) + > + { + [StubStatement] + ^exactlyOnce R|/x|.R|SubstitutionOverride|() + } + public final fun atMostOnce(x: R|() -> T|): R|T| + [R|Contract description] + < + CallsInPlace(x, AT_MOST_ONCE) + > + { + [StubStatement] + ^atMostOnce R|/x|.R|SubstitutionOverride|() + } + public final fun noContract(x: R|() -> T|): R|T| { + ^noContract R|/x|.R|SubstitutionOverride|() } public final fun select(vararg x: R|kotlin/Array|): R|K| { ^select R|/x|.R|SubstitutionOverride|(Int(0)) @@ -10,64 +47,169 @@ FILE: flowFromInplaceLambda.kt public final fun materialize(): R|K| { ^materialize Null(null)!! } - public final fun myRun(block: R|() -> R|): R|R| { - ^myRun R|/block|.R|SubstitutionOverride|() - } - public final fun test_1(x: R|kotlin/Any|): R|kotlin/Unit| { - R|kotlin/run|( = run@fun (): R|kotlin/Int| { + public final fun basic(x: R|kotlin/Any?|): R|kotlin/Unit| { + R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Int| { ^ (R|/x| as R|kotlin/Int|) } ) - R|/takeInt|(R|/x|) + R|/x|.R|kotlin/Int.inc|() } - public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int| { + public final fun completedCallExactlyOnce(x: R|kotlin/Any?|, y: R|kotlin/Any?|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Int| { R|/y|.#() ^ (R|/x| as R|kotlin/Int|) } - )), (R|/y| as R|kotlin/Int|), R|kotlin/run|( = run@fun (): R|kotlin/Int| { + )), (R|/y| as R|kotlin/Int|), R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Int| { R|/x|.R|kotlin/Int.inc|() R|/y|.R|kotlin/Int.inc|() ^ Int(1) } - ))) - R|/takeInt|(R|/x|) - R|/takeInt|(R|/y|) - R|/takeInt|(R|/a|) + ))).R|kotlin/Int.inc|() + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() } - public final fun test_3(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int| { + public final fun completedCallAtLeastOnce(x: R|kotlin/Any?|, y: R|kotlin/Any?|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/atLeastOnce|( = atLeastOnce@fun (): R|kotlin/Int| { R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|/atLeastOnce|( = atLeastOnce@fun (): R|kotlin/Int| { + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() + } + public final fun completedCallAtMostOnce(x: R|kotlin/Any?|, y: R|kotlin/Any?|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/atMostOnce|( = atMostOnce@fun (): R|kotlin/Int| { + R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|/atMostOnce|( = atMostOnce@fun (): R|kotlin/Int| { + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + } + public final fun completedCallUnknown(x: R|kotlin/Any?|, y: R|kotlin/Any?|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/unknown|( = unknown@fun (): R|kotlin/Int| { + R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|/unknown|( = unknown@fun (): R|kotlin/Int| { + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + } + public final fun completedCallNoContract(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/noContract|( = noContract@fun (): R|kotlin/Int| { + R|/y|.#() + ^ (R|/x| as R|kotlin/Int|) + } + )), (R|/y| as R|kotlin/Int|), R|/noContract|( = noContract@fun (): R|kotlin/Int| { + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + } + public final fun incompleteCallExactlyOnce(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Int| { (R|/x| as R|kotlin/Int|) + R|/y|.#() + R|/x|.R|kotlin/Int.inc|() ^ R|/materialize|() } - )), R|kotlin/run|( = run@fun (): R|kotlin/Int| { + )), R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Int| { (R|/y| as R|kotlin/Int|) R|/x|.#() R|/y|.R|kotlin/Int.inc|() ^ Int(1) } - ))) - R|/takeInt|(R|/x|) - R|/takeInt|(R|/y|) - R|/takeInt|(R|/a|) + ))).R|kotlin/Int.inc|() + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() } - public final fun test_4(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - lval a: R|kotlin/Int| = R|/select|(vararg(R|/id|(R|/myRun|( = myRun@fun (): R|kotlin/Int| { + public final fun incompleteCallAtLeastOnce(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/atLeastOnce|( = atLeastOnce@fun (): R|kotlin/Int| { + (R|/x| as R|kotlin/Int|) R|/y|.#() - ^ (R|/x| as R|kotlin/Int|) + R|/x|.R|kotlin/Int.inc|() + ^ R|/materialize|() } - )), (R|/y| as R|kotlin/Int|), R|/myRun|( = myRun@fun (): R|kotlin/Int| { + )), R|/atLeastOnce|( = atLeastOnce@fun (): R|kotlin/Int| { + (R|/y| as R|kotlin/Int|) R|/x|.#() R|/y|.R|kotlin/Int.inc|() ^ Int(1) } - ))) - #(R|/x|) - R|/takeInt|(R|/y|) - R|/takeInt|(R|/a|) + ))).R|kotlin/Int.inc|() + R|/x|.R|kotlin/Int.inc|() + R|/y|.R|kotlin/Int.inc|() } - public final fun test_5(): R|kotlin/Unit| { + public final fun incompleteCallAtMostOnce(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/atMostOnce|( = atMostOnce@fun (): R|kotlin/Int| { + (R|/x| as R|kotlin/Int|) + R|/y|.#() + R|/x|.R|kotlin/Int.inc|() + ^ R|/materialize|() + } + )), R|/atMostOnce|( = atMostOnce@fun (): R|kotlin/Int| { + (R|/y| as R|kotlin/Int|) + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.#() + } + public final fun incompleteCallUnknown(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/unknown|( = unknown@fun (): R|kotlin/Int| { + (R|/x| as R|kotlin/Int|) + R|/y|.#() + R|/x|.R|kotlin/Int.inc|() + ^ R|/materialize|() + } + )), R|/unknown|( = unknown@fun (): R|kotlin/Int| { + (R|/y| as R|kotlin/Int|) + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.#() + } + public final fun incompleteCallNoContract(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { + R|/select|(vararg(R|/id|(R|/noContract|( = noContract@fun (): R|kotlin/Int| { + (R|/x| as R|kotlin/Int|) + R|/y|.#() + R|/x|.R|kotlin/Int.inc|() + ^ R|/materialize|() + } + )), R|/noContract|( = noContract@fun (): R|kotlin/Int| { + (R|/y| as R|kotlin/Int|) + R|/x|.#() + R|/y|.R|kotlin/Int.inc|() + ^ Int(1) + } + ))).R|kotlin/Int.inc|() + R|/x|.#() + R|/y|.#() + } + public final fun expectedType(): R|kotlin/Unit| { lval x: R|kotlin/Int| = R|/select|(vararg(R|kotlin/run|( = run@fun (): R|kotlin/Int| { ^ R|/materialize|() } @@ -75,14 +217,15 @@ FILE: flowFromInplaceLambda.kt ^ R|/materialize|() } ))) - R|/takeInt|(R|/x|) + R|/x|.R|kotlin/Int.inc|() } - public final fun test_6(): R|kotlin/Unit| { - lval x: R|kotlin/String| = R|/id|(R|/myRun|( = myRun@fun (): R|kotlin/String| { - ^ R|kotlin/run|( = run@fun (): R|kotlin/String| { - ^ R|/materialize|() + public final fun expectedTypeNested(): R|kotlin/Unit| { + lval x: R|kotlin/Int| = R|/id|(R|/noContract|( = noContract@fun (): R|kotlin/Int| { + ^ R|kotlin/run|( = run@fun (): R|kotlin/Int| { + ^ R|/materialize|() } ) } )) + R|/x|.R|kotlin/Int.inc|() } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt index 6d36b74cadf..6b35a604d9a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt @@ -1,93 +1,141 @@ // !DUMP_CFG -fun takeInt(x: Int) {} +import kotlin.contracts.* + +fun unknown(x: () -> T): T { + contract { callsInPlace(x, InvocationKind.UNKNOWN) } + return x() +} + +fun atLeastOnce(x: () -> T): T { + contract { callsInPlace(x, InvocationKind.AT_LEAST_ONCE) } + return x() +} + +fun exactlyOnce(x: () -> T): T { + contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) } + return x() +} + +fun atMostOnce(x: () -> T): T { + contract { callsInPlace(x, InvocationKind.AT_MOST_ONCE) } + return x() +} + +fun noContract(x: () -> T): T = x() fun select(vararg x: K): K = x[0] fun id(x: T): T = x fun materialize(): K = null!! -fun myRun(block: () -> R): R = block() - -fun test_1(x: Any) { - run { - x as Int - } - takeInt(x) // OK +fun basic(x: Any?) { + exactlyOnce { x as Int } + x.inc() // OK } -fun test_2(x: Any, y: Any) { - val a = select( - id( - run { - y.inc() // Bad - x as Int - } - ), +fun completedCallExactlyOnce(x: Any?, y: Any?) { + select( + // The value of the type argument is known, so the call is complete and the data can flow. + id(exactlyOnce { y.inc(); x as Int }), y as Int, - run { - x.inc() // Should be "Bad" but "OK" is fine - y.inc() // OK - 1 - } - ) - takeInt(x) // OK - takeInt(y) // OK - takeInt(a) // OK + exactlyOnce { x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // OK + y.inc() // OK } -fun test_3(x: Any, y: Any) { - val a = select( - id( - run { - y.inc() // Bad - x as Int - materialize() - } - ), - run { - y as Int - x.inc() // Bad - y.inc() // OK - 1 - } - ) - takeInt(x) // OK - takeInt(y) // OK - takeInt(a) // OK -} - -fun test_4(x: Any, y: Any) { - val a = select( - id( - myRun { - y.inc() // Bad - x as Int - } - ), +fun completedCallAtLeastOnce(x: Any?, y: Any?) { + select( + id(atLeastOnce { y.inc(); x as Int }), y as Int, - myRun { - x.inc() // Bad - y.inc() // OK - 1 - } - - ) - takeInt(x) // Bad - takeInt(y) // OK - takeInt(a) // Bad + atLeastOnce { x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // OK + y.inc() // OK } -fun test_5() { +fun completedCallAtMostOnce(x: Any?, y: Any?) { + select( + id(atMostOnce { y.inc(); x as Int }), + y as Int, + atMostOnce { x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // OK +} + +fun completedCallUnknown(x: Any?, y: Any?) { + select( + id(unknown { y.inc(); x as Int }), + y as Int, + unknown { x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // OK +} + +fun completedCallNoContract(x: Any, y: Any) { + select( + id(noContract { y.inc(); x as Int }), + y as Int, + noContract { x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // OK +} + +fun incompleteCallExactlyOnce(x: Any, y: Any) { + select( + // The type argument is uninferred, so the two lambdas are concurrent by data flow. + id(exactlyOnce { x as Int; y.inc(); x.inc(); materialize() }), + exactlyOnce { y as Int; x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // OK + y.inc() // OK +} + +fun incompleteCallAtLeastOnce(x: Any, y: Any) { + select( + id(atLeastOnce { x as Int; y.inc(); x.inc(); materialize() }), + atLeastOnce { y as Int; x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // OK + y.inc() // OK +} + +fun incompleteCallAtMostOnce(x: Any, y: Any) { + select( + id(atMostOnce { x as Int; y.inc(); x.inc(); materialize() }), + atMostOnce { y as Int; x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // Bad: y as Int might not have executed +} + +fun incompleteCallUnknown(x: Any, y: Any) { + select( + id(unknown { x as Int; y.inc(); x.inc(); materialize() }), + unknown { y as Int; x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // Bad: y as Int might not have executed +} + +fun incompleteCallNoContract(x: Any, y: Any) { + select( + id(noContract { x as Int; y.inc(); x.inc(); materialize() }), + noContract { y as Int; x.inc(); y.inc(); 1 } + ).inc() // OK + x.inc() // Bad: x as Int might not have executed + y.inc() // Bad: y as Int might not have executed +} + +fun expectedType() { val x: Int = select(run { materialize() }, run { materialize() }) - takeInt(x) + x.inc() } -fun test_6() { - val x: String = id( - myRun { - run { - materialize() - } - } - ) +fun expectedTypeNested() { + val x: Int = id(noContract { run { materialize() } }) + x.inc() } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot index 35b54feff8e..35d6a5f90ae 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot @@ -127,7 +127,7 @@ digraph flowFromInplaceLambda3_kt { subgraph cluster_12 { color=red - 42 [label="Enter function test2" style="filled" fillcolor=red]; + 42 [label="Enter function test1m" style="filled" fillcolor=red]; subgraph cluster_13 { color=blue 43 [label="Enter block"]; @@ -140,28 +140,23 @@ digraph flowFromInplaceLambda3_kt { 50 [label="Postponed enter to lambda"]; subgraph cluster_14 { color=blue - 62 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 57 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_15 { color=blue - 63 [label="Enter block"]; - 64 [label="Const: Int(1)"]; - 65 [label="Assignment: R|/x|"]; - 66 [label="Exit block"]; + 58 [label="Enter block"]; + 59 [label="Const: String()"]; + 60 [label="Assignment: R|/x|"]; + 61 [label="Exit block"]; } - 67 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 62 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 51 [label="Call arguments union" style="filled" fillcolor=yellow]; - 52 [label="Postponed exit from lambda"]; - 53 [label="Function call: R|/atLeastOnce|(...)"]; - 54 [label="Access variable R|/x|"]; - 55 [label="Smart cast: R|/x|"]; - 56 [label="Access variable #"]; - 57 [label="Access variable R|/x|"]; - 58 [label="Smart cast: R|/x|"]; - 59 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; - 60 [label="Exit block"]; + 51 [label="Postponed exit from lambda"]; + 52 [label="Function call: R|/unknown|(...)"]; + 53 [label="Access variable R|/x|"]; + 54 [label="Access variable #"]; + 55 [label="Exit block"]; } - 61 [label="Exit function test2" style="filled" fillcolor=red]; + 56 [label="Exit function test1m" style="filled" fillcolor=red]; } 42 -> {43}; 43 -> {44}; @@ -171,157 +166,217 @@ digraph flowFromInplaceLambda3_kt { 47 -> {48}; 48 -> {49}; 49 -> {50}; - 50 -> {62}; - 50 -> {52} [color=red]; - 50 -> {62} [style=dashed]; - 51 -> {53} [color=red]; - 52 -> {53} [color=green]; + 50 -> {51 57}; + 50 -> {57} [style=dashed]; + 51 -> {52}; + 52 -> {53}; 53 -> {54}; 54 -> {55}; 55 -> {56}; - 56 -> {57}; - 57 -> {58}; + 57 -> {62 58}; 58 -> {59}; 59 -> {60}; 60 -> {61}; - 62 -> {63}; + 61 -> {62}; + 62 -> {51}; + 62 -> {57} [color=green style=dashed]; + + subgraph cluster_16 { + color=red + 63 [label="Enter function test2" style="filled" fillcolor=red]; + subgraph cluster_17 { + color=blue + 64 [label="Enter block"]; + 65 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 66 [label="Const: String()"]; + 67 [label="Assignment: R|/x|"]; + 68 [label="Access variable R|/x|"]; + 69 [label="Smart cast: R|/x|"]; + 70 [label="Access variable R|kotlin/String.length|"]; + 71 [label="Postponed enter to lambda"]; + subgraph cluster_18 { + color=blue + 83 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_19 { + color=blue + 84 [label="Enter block"]; + 85 [label="Const: Int(1)"]; + 86 [label="Assignment: R|/x|"]; + 87 [label="Exit block"]; + } + 88 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 72 [label="Call arguments union" style="filled" fillcolor=yellow]; + 73 [label="Postponed exit from lambda"]; + 74 [label="Function call: R|/atLeastOnce|(...)"]; + 75 [label="Access variable R|/x|"]; + 76 [label="Smart cast: R|/x|"]; + 77 [label="Access variable #"]; + 78 [label="Access variable R|/x|"]; + 79 [label="Smart cast: R|/x|"]; + 80 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 81 [label="Exit block"]; + } + 82 [label="Exit function test2" style="filled" fillcolor=red]; + } 63 -> {64}; 64 -> {65}; 65 -> {66}; 66 -> {67}; - 67 -> {51} [color=red]; - 67 -> {52} [color=green]; - 67 -> {62} [color=green style=dashed]; - - subgraph cluster_16 { - color=red - 68 [label="Enter function test3" style="filled" fillcolor=red]; - subgraph cluster_17 { - color=blue - 69 [label="Enter block"]; - 70 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 71 [label="Const: String()"]; - 72 [label="Assignment: R|/x|"]; - 73 [label="Access variable R|/x|"]; - 74 [label="Smart cast: R|/x|"]; - 75 [label="Access variable R|kotlin/String.length|"]; - 76 [label="Postponed enter to lambda"]; - subgraph cluster_18 { - color=blue - 88 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 89 [label="Enter block"]; - 90 [label="Const: Int(1)"]; - 91 [label="Assignment: R|/x|"]; - 92 [label="Exit block"]; - } - 93 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 77 [label="Call arguments union" style="filled" fillcolor=yellow]; - 78 [label="Postponed exit from lambda"]; - 79 [label="Function call: R|/exactlyOnce|(...)"]; - 80 [label="Access variable R|/x|"]; - 81 [label="Smart cast: R|/x|"]; - 82 [label="Access variable #"]; - 83 [label="Access variable R|/x|"]; - 84 [label="Smart cast: R|/x|"]; - 85 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; - 86 [label="Exit block"]; - } - 87 [label="Exit function test3" style="filled" fillcolor=red]; - } + 67 -> {68}; 68 -> {69}; 69 -> {70}; 70 -> {71}; - 71 -> {72}; - 72 -> {73}; - 73 -> {74}; + 71 -> {83}; + 71 -> {73} [color=red]; + 71 -> {83} [style=dashed]; + 72 -> {74} [color=red]; + 73 -> {74} [color=green]; 74 -> {75}; 75 -> {76}; - 76 -> {88}; - 76 -> {78} [color=red]; - 76 -> {88} [style=dashed]; - 77 -> {79} [color=red]; - 78 -> {79} [color=green]; + 76 -> {77}; + 77 -> {78}; + 78 -> {79}; 79 -> {80}; 80 -> {81}; 81 -> {82}; - 82 -> {83}; 83 -> {84}; 84 -> {85}; 85 -> {86}; 86 -> {87}; - 88 -> {89}; + 87 -> {88}; + 88 -> {72} [color=red]; + 88 -> {73} [color=green]; + 88 -> {83} [color=green style=dashed]; + + subgraph cluster_20 { + color=red + 89 [label="Enter function test3" style="filled" fillcolor=red]; + subgraph cluster_21 { + color=blue + 90 [label="Enter block"]; + 91 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 92 [label="Const: String()"]; + 93 [label="Assignment: R|/x|"]; + 94 [label="Access variable R|/x|"]; + 95 [label="Smart cast: R|/x|"]; + 96 [label="Access variable R|kotlin/String.length|"]; + 97 [label="Postponed enter to lambda"]; + subgraph cluster_22 { + color=blue + 109 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_23 { + color=blue + 110 [label="Enter block"]; + 111 [label="Const: Int(1)"]; + 112 [label="Assignment: R|/x|"]; + 113 [label="Exit block"]; + } + 114 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 98 [label="Call arguments union" style="filled" fillcolor=yellow]; + 99 [label="Postponed exit from lambda"]; + 100 [label="Function call: R|/exactlyOnce|(...)"]; + 101 [label="Access variable R|/x|"]; + 102 [label="Smart cast: R|/x|"]; + 103 [label="Access variable #"]; + 104 [label="Access variable R|/x|"]; + 105 [label="Smart cast: R|/x|"]; + 106 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 107 [label="Exit block"]; + } + 108 [label="Exit function test3" style="filled" fillcolor=red]; + } 89 -> {90}; 90 -> {91}; 91 -> {92}; 92 -> {93}; - 93 -> {77} [color=red]; - 93 -> {78} [color=green]; - 93 -> {88} [color=green style=dashed]; - - subgraph cluster_20 { - color=red - 94 [label="Enter function test4" style="filled" fillcolor=red]; - subgraph cluster_21 { - color=blue - 95 [label="Enter block"]; - 96 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 97 [label="Const: String()"]; - 98 [label="Assignment: R|/x|"]; - 99 [label="Access variable R|/x|"]; - 100 [label="Smart cast: R|/x|"]; - 101 [label="Access variable R|kotlin/String.length|"]; - 102 [label="Postponed enter to lambda"]; - subgraph cluster_22 { - color=blue - 113 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_23 { - color=blue - 114 [label="Enter block"]; - 115 [label="Const: Int(1)"]; - 116 [label="Assignment: R|/x|"]; - 117 [label="Exit block"]; - } - 118 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 103 [label="Postponed exit from lambda"]; - 104 [label="Function call: R|/atMostOnce|(...)"]; - 105 [label="Access variable R|/x|"]; - 106 [label="Smart cast: R|/x|"]; - 107 [label="Access variable #"]; - 108 [label="Access variable R|/x|"]; - 109 [label="Smart cast: R|/x|"]; - 110 [label="Function call: R|/x|.#()"]; - 111 [label="Exit block"]; - } - 112 [label="Exit function test4" style="filled" fillcolor=red]; - } + 93 -> {94}; 94 -> {95}; 95 -> {96}; 96 -> {97}; - 97 -> {98}; - 98 -> {99}; - 99 -> {100}; + 97 -> {109}; + 97 -> {99} [color=red]; + 97 -> {109} [style=dashed]; + 98 -> {100} [color=red]; + 99 -> {100} [color=green]; 100 -> {101}; 101 -> {102}; - 102 -> {103 113}; - 102 -> {113} [style=dashed]; + 102 -> {103}; 103 -> {104}; 104 -> {105}; 105 -> {106}; 106 -> {107}; 107 -> {108}; - 108 -> {109}; 109 -> {110}; 110 -> {111}; 111 -> {112}; - 113 -> {118 114}; - 114 -> {115}; + 112 -> {113}; + 113 -> {114}; + 114 -> {98} [color=red]; + 114 -> {99} [color=green]; + + subgraph cluster_24 { + color=red + 115 [label="Enter function test4" style="filled" fillcolor=red]; + subgraph cluster_25 { + color=blue + 116 [label="Enter block"]; + 117 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 118 [label="Const: String()"]; + 119 [label="Assignment: R|/x|"]; + 120 [label="Access variable R|/x|"]; + 121 [label="Smart cast: R|/x|"]; + 122 [label="Access variable R|kotlin/String.length|"]; + 123 [label="Postponed enter to lambda"]; + subgraph cluster_26 { + color=blue + 134 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_27 { + color=blue + 135 [label="Enter block"]; + 136 [label="Const: Int(1)"]; + 137 [label="Assignment: R|/x|"]; + 138 [label="Exit block"]; + } + 139 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 124 [label="Postponed exit from lambda"]; + 125 [label="Function call: R|/atMostOnce|(...)"]; + 126 [label="Access variable R|/x|"]; + 127 [label="Smart cast: R|/x|"]; + 128 [label="Access variable #"]; + 129 [label="Access variable R|/x|"]; + 130 [label="Smart cast: R|/x|"]; + 131 [label="Function call: R|/x|.#()"]; + 132 [label="Exit block"]; + } + 133 [label="Exit function test4" style="filled" fillcolor=red]; + } 115 -> {116}; 116 -> {117}; 117 -> {118}; - 118 -> {103}; + 118 -> {119}; + 119 -> {120}; + 120 -> {121}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124 134}; + 123 -> {134} [style=dashed]; + 124 -> {125}; + 125 -> {126}; + 126 -> {127}; + 127 -> {128}; + 128 -> {129}; + 129 -> {130}; + 130 -> {131}; + 131 -> {132}; + 132 -> {133}; + 134 -> {139 135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; + 138 -> {139}; + 139 -> {124}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt index 3474741ccad..58810e43606 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt @@ -20,7 +20,7 @@ FILE: flowFromInplaceLambda3.kt public final fun exactlyOnce(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < - CallsInPlace(x, AT_LEAST_ONCE) + CallsInPlace(x, EXACTLY_ONCE) > { [StubStatement] @@ -45,6 +45,16 @@ FILE: flowFromInplaceLambda3.kt R|/x|.# R|/x|.#() } + public final fun test1m(): R|kotlin/Unit| { + lvar x: R|kotlin/Any?| + R|/x| = String() + R|/x|.R|kotlin/String.length| + R|/unknown|( = unknown@fun (): R|kotlin/Unit| { + R|/x| = String() + } + ) + R|/x|.# + } public final fun test2(): R|kotlin/Unit| { lvar x: R|kotlin/Any?| R|/x| = String() @@ -60,7 +70,7 @@ FILE: flowFromInplaceLambda3.kt lvar x: R|kotlin/Any?| R|/x| = String() R|/x|.R|kotlin/String.length| - R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Unit| { + R|/exactlyOnce|( = exactlyOnce@fun (): R|kotlin/Unit| { R|/x| = Int(1) } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt index f90bdac6c95..5de255da7ee 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt @@ -13,7 +13,7 @@ fun atLeastOnce(x: () -> Unit) { } fun exactlyOnce(x: () -> Unit) { - contract { callsInPlace(x, InvocationKind.AT_LEAST_ONCE) } + contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) } x() } @@ -30,6 +30,14 @@ fun test1() { x.inc() } +fun test1m() { + var x: Any? + x = "" + x.length + unknown { x = "" } + x.length +} + fun test2() { var x: Any? x = "" diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot index d7f3d824534..bc990cbee27 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot @@ -682,4 +682,192 @@ digraph flowFromTwoInplaceLambdas_kt { 248 -> {220} [color=red]; 248 -> {223} [color=green]; + subgraph cluster_48 { + color=red + 249 [label="Enter function test6" style="filled" fillcolor=red]; + subgraph cluster_49 { + color=blue + 250 [label="Enter block"]; + 251 [label="Variable declaration: lval x: R|kotlin/String|"]; + 252 [label="Postponed enter to lambda"]; + subgraph cluster_50 { + color=blue + 262 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_51 { + color=blue + 263 [label="Enter block"]; + 264 [label="Const: String()"]; + 265 [label="Assignment: R|/x|"]; + 266 [label="Access variable R|/x|"]; + 267 [label="Access variable R|kotlin/String.length|"]; + 268 [label="Exit block"]; + } + 269 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 254 [label="Postponed exit from lambda"]; + 255 [label="Postponed enter to lambda"]; + subgraph cluster_52 { + color=blue + 270 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_53 { + color=blue + 271 [label="Enter block"]; + 272 [label="Access variable R|/x|"]; + 273 [label="Access variable R|kotlin/String.length|"]; + 274 [label="Exit block"]; + } + 275 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 253 [label="Call arguments union" style="filled" fillcolor=yellow]; + 256 [label="Postponed exit from lambda"]; + 257 [label="Function call: R|/run2|(...)"]; + 258 [label="Access variable R|/x|"]; + 259 [label="Access variable R|kotlin/String.length|"]; + 260 [label="Exit block"]; + } + 261 [label="Exit function test6" style="filled" fillcolor=red]; + } + 249 -> {250}; + 250 -> {251}; + 251 -> {252}; + 252 -> {262}; + 252 -> {254} [color=red]; + 252 -> {262} [style=dashed]; + 253 -> {257} [color=red]; + 254 -> {255}; + 255 -> {270}; + 255 -> {256} [color=red]; + 255 -> {270} [style=dashed]; + 256 -> {257} [color=green]; + 257 -> {258}; + 258 -> {259}; + 259 -> {260}; + 260 -> {261}; + 262 -> {263}; + 263 -> {264}; + 264 -> {265}; + 265 -> {266}; + 266 -> {267}; + 267 -> {268}; + 268 -> {269}; + 269 -> {253} [color=red]; + 269 -> {254} [color=green]; + 270 -> {271}; + 271 -> {272}; + 272 -> {273}; + 273 -> {274}; + 274 -> {275}; + 275 -> {253} [color=red]; + 275 -> {256} [color=green]; + + subgraph cluster_54 { + color=red + 276 [label="Enter function test7" style="filled" fillcolor=red]; + subgraph cluster_55 { + color=blue + 277 [label="Enter block"]; + 278 [label="Const: String()"]; + 279 [label="Variable declaration: lval x: R|kotlin/Any?|"]; + 280 [label="Variable declaration: lval y: R|kotlin/Any?|"]; + 281 [label="Postponed enter to lambda"]; + subgraph cluster_56 { + color=blue + 302 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_57 { + color=blue + 303 [label="Enter block"]; + 304 [label="Access variable R|/x|"]; + 305 [label="Assignment: R|/y|"]; + 306 [label="Exit block"]; + } + 307 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 283 [label="Postponed exit from lambda"]; + 284 [label="Postponed enter to lambda"]; + subgraph cluster_58 { + color=blue + 308 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_59 { + color=blue + 309 [label="Enter block"]; + 310 [label="Jump: ^@run2 Unit"]; + 311 [label="Stub" style="filled" fillcolor=gray]; + 312 [label="Exit block" style="filled" fillcolor=gray]; + } + 313 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 282 [label="Call arguments union" style="filled" fillcolor=yellow]; + 285 [label="Postponed exit from lambda"]; + 286 [label="Function call: R|/run2|(...)"]; + subgraph cluster_60 { + color=blue + 287 [label="Enter when"]; + subgraph cluster_61 { + color=blue + 288 [label="Enter when branch condition "]; + 289 [label="Access variable R|/y|"]; + 290 [label="Type operator: (R|/y| is R|kotlin/String|)"]; + 291 [label="Exit when branch condition"]; + } + 292 [label="Synthetic else branch"]; + 293 [label="Enter when branch result"]; + subgraph cluster_62 { + color=blue + 294 [label="Enter block"]; + 295 [label="Access variable R|/x|"]; + 296 [label="Access variable #"]; + 297 [label="Exit block"]; + } + 298 [label="Exit when branch result"]; + 299 [label="Exit when"]; + } + 300 [label="Exit block"]; + } + 301 [label="Exit function test7" style="filled" fillcolor=red]; + } + 276 -> {277}; + 277 -> {278}; + 278 -> {279}; + 279 -> {280}; + 280 -> {281}; + 281 -> {302}; + 281 -> {283} [color=red]; + 281 -> {302} [style=dashed]; + 282 -> {286} [color=red]; + 283 -> {284}; + 284 -> {308}; + 284 -> {285} [color=red]; + 284 -> {308} [style=dashed]; + 285 -> {286} [color=green]; + 286 -> {287}; + 287 -> {288}; + 288 -> {289}; + 289 -> {290}; + 290 -> {291}; + 291 -> {293 292}; + 292 -> {299}; + 293 -> {294}; + 294 -> {295}; + 295 -> {296}; + 296 -> {297}; + 297 -> {298}; + 298 -> {299}; + 299 -> {300}; + 300 -> {301}; + 302 -> {303}; + 303 -> {304}; + 304 -> {305}; + 305 -> {306}; + 306 -> {307}; + 307 -> {282} [color=red]; + 307 -> {283} [color=green]; + 308 -> {309}; + 309 -> {310}; + 310 -> {313}; + 310 -> {311} [style=dotted]; + 311 -> {312} [style=dotted]; + 312 -> {313} [style=dotted]; + 313 -> {282} [color=red]; + 313 -> {285} [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 d40af10d969..a2e7e2fc301 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt @@ -121,3 +121,32 @@ FILE: flowFromTwoInplaceLambdas.kt R|/p|.# R|/p|?.{ $subj$.R|kotlin/String.length| } } + public final fun test6(): R|kotlin/Unit| { + lval x: R|kotlin/String| + R|/run2|(run2@fun (): R|kotlin/Int| { + R|/x| = String() + ^ R|/x|.R|kotlin/String.length| + } + , run2@fun (): R|kotlin/Int| { + ^ R|/x|.R|kotlin/String.length| + } + ) + R|/x|.R|kotlin/String.length| + } + public final fun test7(): R|kotlin/Unit| { + lval x: R|kotlin/Any?| = String() + lval y: R|kotlin/Any?| + R|/run2|(run2@fun (): R|kotlin/Unit| { + R|/y| = R|/x| + } + , run2@fun (): R|kotlin/Unit| { + ^@run2 Unit + } + ) + when () { + (R|/y| is R|kotlin/String|) -> { + R|/x|.# + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt index 94faaddb5f4..6fd04d5ac4c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt @@ -71,3 +71,19 @@ fun test5(x: Any?, q: String?) { p.length // Bad: p is String? | (String? & Int) = String? p?.length // OK: p is String? } + +fun test6() { + val x: String + // not necessarily initialized in second lambda (may call in any order) + run2({ x = ""; x.length }, { x.length }) + x.length // initialized here +} + +fun test7() { + val x: Any? = "" + val y: Any? + run2({ y = x }, { }) + if (y is String) { + x.length // ok - aliased + } +}