diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index 23a4244a23c..f5c4b991198 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -5193,6 +5193,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("noOptIn.kt") + public void testNoOptIn() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace") @TestDataPath("$PROJECT_ROOT") @@ -5247,6 +5253,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis public void testPropertyGetter() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.kt"); } + + @Test + @TestMetadata("redundantConditions.kt") + public void testRedundantConditions() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt"); + } } } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot index 10526d930c1..de254681689 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot @@ -9,337 +9,261 @@ digraph flowFromInplaceLambda_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Jump: ^unknown R|/x|.R|SubstitutionOverride|()"]; - 4 [label="Stub" style="filled" fillcolor=gray]; - 5 [label="Exit block" style="filled" fillcolor=gray]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Jump: ^unknown R|/x|.R|SubstitutionOverride|()"]; + 6 [label="Stub" style="filled" fillcolor=gray]; + 7 [label="Exit block" style="filled" fillcolor=gray]; } - 6 [label="Exit function unknown" style="filled" fillcolor=red]; + 8 [label="Exit function unknown" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; - 3 -> {6}; - 3 -> {4} [style=dotted]; - 4 -> {5} [style=dotted]; + 3 -> {4}; + 4 -> {5}; + 5 -> {8}; 5 -> {6} [style=dotted]; + 6 -> {7} [style=dotted]; + 7 -> {8} [style=dotted]; - subgraph cluster_2 { + subgraph cluster_3 { color=red - 7 [label="Enter function atLeastOnce" style="filled" fillcolor=red]; - subgraph cluster_3 { + 17 [label="Enter function atLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 8 [label="Enter block"]; - 9 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 10 [label="Jump: ^atLeastOnce R|/x|.R|SubstitutionOverride|()"]; - 11 [label="Stub" style="filled" fillcolor=gray]; - 12 [label="Exit block" style="filled" fillcolor=gray]; + 18 [label="Enter block"]; + subgraph cluster_5 { + color=blue + 19 [label="Enter block"]; + 20 [label="Exit block"]; + } + 21 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 22 [label="Jump: ^atLeastOnce R|/x|.R|SubstitutionOverride|()"]; + 23 [label="Stub" style="filled" fillcolor=gray]; + 24 [label="Exit block" style="filled" fillcolor=gray]; } - 13 [label="Exit function atLeastOnce" style="filled" fillcolor=red]; + 25 [label="Exit function atLeastOnce" style="filled" fillcolor=red]; } - 7 -> {8}; - 8 -> {9}; - 9 -> {10}; - 10 -> {13}; - 10 -> {11} [style=dotted]; - 11 -> {12} [style=dotted]; - 12 -> {13} [style=dotted]; - - subgraph cluster_4 { - color=red - 14 [label="Enter function exactlyOnce" style="filled" fillcolor=red]; - subgraph cluster_5 { - color=blue - 15 [label="Enter block"]; - 16 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 17 [label="Jump: ^exactlyOnce R|/x|.R|SubstitutionOverride|()"]; - 18 [label="Stub" style="filled" fillcolor=gray]; - 19 [label="Exit block" style="filled" fillcolor=gray]; - } - 20 [label="Exit function exactlyOnce" style="filled" fillcolor=red]; - } - 14 -> {15}; - 15 -> {16}; - 16 -> {17}; - 17 -> {20}; - 17 -> {18} [style=dotted]; - 18 -> {19} [style=dotted]; - 19 -> {20} [style=dotted]; + 17 -> {18}; + 18 -> {19}; + 19 -> {20}; + 20 -> {21}; + 21 -> {22}; + 22 -> {25}; + 22 -> {23} [style=dotted]; + 23 -> {24} [style=dotted]; + 24 -> {25} [style=dotted]; subgraph cluster_6 { color=red - 21 [label="Enter function atMostOnce" style="filled" fillcolor=red]; + 34 [label="Enter function exactlyOnce" style="filled" fillcolor=red]; subgraph cluster_7 { color=blue - 22 [label="Enter block"]; - 23 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 24 [label="Jump: ^atMostOnce R|/x|.R|SubstitutionOverride|()"]; - 25 [label="Stub" style="filled" fillcolor=gray]; - 26 [label="Exit block" style="filled" fillcolor=gray]; + 35 [label="Enter block"]; + subgraph cluster_8 { + color=blue + 36 [label="Enter block"]; + 37 [label="Exit block"]; + } + 38 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 39 [label="Jump: ^exactlyOnce R|/x|.R|SubstitutionOverride|()"]; + 40 [label="Stub" style="filled" fillcolor=gray]; + 41 [label="Exit block" style="filled" fillcolor=gray]; } - 27 [label="Exit function atMostOnce" style="filled" fillcolor=red]; - } - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {27}; - 24 -> {25} [style=dotted]; - 25 -> {26} [style=dotted]; - 26 -> {27} [style=dotted]; - - subgraph cluster_8 { - color=red - 28 [label="Enter function noContract" style="filled" fillcolor=red]; - subgraph cluster_9 { - color=blue - 29 [label="Enter block"]; - 30 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 31 [label="Jump: ^noContract R|/x|.R|SubstitutionOverride|()"]; - 32 [label="Stub" style="filled" fillcolor=gray]; - 33 [label="Exit block" style="filled" fillcolor=gray]; - } - 34 [label="Exit function noContract" style="filled" fillcolor=red]; - } - 28 -> {29}; - 29 -> {30}; - 30 -> {31}; - 31 -> {34}; - 31 -> {32} [style=dotted]; - 32 -> {33} [style=dotted]; - 33 -> {34} [style=dotted]; - - subgraph cluster_10 { - color=red - 35 [label="Enter function select" style="filled" fillcolor=red]; - subgraph cluster_11 { - color=blue - 36 [label="Enter block"]; - 37 [label="Access variable R|/x|"]; - 38 [label="Const: Int(0)"]; - 39 [label="Function call: R|/x|.R|SubstitutionOverride|(...)" style="filled" fillcolor=yellow]; - 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]; - } - 43 [label="Exit function select" style="filled" fillcolor=red]; + 42 [label="Exit function exactlyOnce" style="filled" fillcolor=red]; } + 34 -> {35}; 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; - 40 -> {43}; + 39 -> {42}; + 39 -> {40} [style=dotted]; 40 -> {41} [style=dotted]; 41 -> {42} [style=dotted]; - 42 -> {43} [style=dotted]; - subgraph cluster_12 { + subgraph cluster_9 { 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}; - 46 -> {47}; - 47 -> {50}; - 47 -> {48} [style=dotted]; - 48 -> {49} [style=dotted]; - 49 -> {50} [style=dotted]; - - subgraph cluster_14 { - color=red - 51 [label="Enter function materialize" style="filled" fillcolor=red]; - subgraph cluster_15 { + 51 [label="Enter function atMostOnce" style="filled" fillcolor=red]; + subgraph cluster_10 { color=blue 52 [label="Enter block"]; - 53 [label="Const: Null(null)"]; - 54 [label="Check not null: Null(null)!!" style="filled" fillcolor=yellow]; - 55 [label="Stub" style="filled" fillcolor=gray]; - 56 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray]; + subgraph cluster_11 { + color=blue + 53 [label="Enter block"]; + 54 [label="Exit block"]; + } + 55 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 56 [label="Jump: ^atMostOnce R|/x|.R|SubstitutionOverride|()"]; 57 [label="Stub" style="filled" fillcolor=gray]; 58 [label="Exit block" style="filled" fillcolor=gray]; } - 59 [label="Exit function materialize" style="filled" fillcolor=red]; + 59 [label="Exit function atMostOnce" 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]; + 54 -> {55}; + 55 -> {56}; + 56 -> {59}; + 56 -> {57} [style=dotted]; 57 -> {58} [style=dotted]; 58 -> {59} [style=dotted]; + subgraph cluster_12 { + color=red + 68 [label="Enter function noContract" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 69 [label="Enter block"]; + 70 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 71 [label="Jump: ^noContract R|/x|.R|SubstitutionOverride|()"]; + 72 [label="Stub" style="filled" fillcolor=gray]; + 73 [label="Exit block" style="filled" fillcolor=gray]; + } + 74 [label="Exit function noContract" style="filled" fillcolor=red]; + } + 68 -> {69}; + 69 -> {70}; + 70 -> {71}; + 71 -> {74}; + 71 -> {72} [style=dotted]; + 72 -> {73} [style=dotted]; + 73 -> {74} [style=dotted]; + + subgraph cluster_14 { + color=red + 75 [label="Enter function select" style="filled" fillcolor=red]; + subgraph cluster_15 { + color=blue + 76 [label="Enter block"]; + 77 [label="Access variable R|/x|"]; + 78 [label="Const: Int(0)"]; + 79 [label="Function call: R|/x|.R|SubstitutionOverride|(...)" style="filled" fillcolor=yellow]; + 80 [label="Jump: ^select R|/x|.R|SubstitutionOverride|(Int(0))"]; + 81 [label="Stub" style="filled" fillcolor=gray]; + 82 [label="Exit block" style="filled" fillcolor=gray]; + } + 83 [label="Exit function select" style="filled" fillcolor=red]; + } + 75 -> {76}; + 76 -> {77}; + 77 -> {78}; + 78 -> {79}; + 79 -> {80}; + 80 -> {83}; + 80 -> {81} [style=dotted]; + 81 -> {82} [style=dotted]; + 82 -> {83} [style=dotted]; + subgraph cluster_16 { color=red - 60 [label="Enter function basic" style="filled" fillcolor=red]; + 84 [label="Enter function id" style="filled" fillcolor=red]; subgraph cluster_17 { color=blue - 61 [label="Enter block"]; - 62 [label="Postponed enter to lambda"]; - subgraph cluster_18 { - color=blue - 70 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 71 [label="Enter block"]; - 72 [label="Access variable R|/x|"]; - 73 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 74 [label="Exit block"]; - } - 75 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 63 [label="Postponed exit from lambda"]; - 64 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 65 [label="Access variable R|/x|"]; - 66 [label="Smart cast: R|/x|"]; - 67 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 68 [label="Exit block"]; + 85 [label="Enter block"]; + 86 [label="Access variable R|/x|"]; + 87 [label="Jump: ^id R|/x|"]; + 88 [label="Stub" style="filled" fillcolor=gray]; + 89 [label="Exit block" style="filled" fillcolor=gray]; } - 69 [label="Exit function basic" style="filled" fillcolor=red]; + 90 [label="Exit function id" style="filled" fillcolor=red]; } - 60 -> {61}; - 61 -> {62}; - 62 -> {70 64}; - 62 -> {63} [style=dotted]; - 62 -> {70} [style=dashed]; - 63 -> {64}; - 64 -> {65}; - 65 -> {66}; - 66 -> {67}; - 67 -> {68}; - 68 -> {69}; - 70 -> {71}; - 71 -> {72}; - 72 -> {73}; - 73 -> {74}; - 74 -> {75}; - 75 -> {63}; + 84 -> {85}; + 85 -> {86}; + 86 -> {87}; + 87 -> {90}; + 87 -> {88} [style=dotted]; + 88 -> {89} [style=dotted]; + 89 -> {90} [style=dotted]; + + subgraph cluster_18 { + color=red + 91 [label="Enter function materialize" style="filled" fillcolor=red]; + subgraph cluster_19 { + color=blue + 92 [label="Enter block"]; + 93 [label="Const: Null(null)"]; + 94 [label="Check not null: Null(null)!!" style="filled" fillcolor=yellow]; + 95 [label="Stub" style="filled" fillcolor=gray]; + 96 [label="Jump: ^materialize Null(null)!!" style="filled" fillcolor=gray]; + 97 [label="Stub" style="filled" fillcolor=gray]; + 98 [label="Exit block" style="filled" fillcolor=gray]; + } + 99 [label="Exit function materialize" style="filled" fillcolor=red]; + } + 91 -> {92}; + 92 -> {93}; + 93 -> {94}; + 94 -> {99} [label=onUncaughtException]; + 94 -> {95} [style=dotted]; + 95 -> {96} [style=dotted]; + 96 -> {99 97} [style=dotted]; + 97 -> {98} [style=dotted]; + 98 -> {99} [style=dotted]; subgraph cluster_20 { color=red - 76 [label="Enter function completedCallExactlyOnce" style="filled" fillcolor=red]; + 100 [label="Enter function basic" style="filled" fillcolor=red]; subgraph cluster_21 { color=blue - 77 [label="Enter block"]; - 78 [label="Postponed enter to lambda"]; + 101 [label="Enter block"]; + 102 [label="Postponed enter to lambda"]; subgraph cluster_22 { color=blue - 97 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 110 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_23 { color=blue - 98 [label="Enter block"]; - 99 [label="Access variable R|/y|"]; - 100 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 101 [label="Access variable R|/x|"]; - 102 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 103 [label="Exit block"]; - } - 104 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 79 [label="Postponed exit from lambda"]; - 80 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 81 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 82 [label="Access variable R|/y|"]; - 83 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 84 [label="Postponed enter to lambda"]; - subgraph cluster_24 { - color=blue - 105 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_25 { - color=blue - 106 [label="Enter block"]; - 107 [label="Access variable R|/x|"]; - 108 [label="Smart cast: R|/x|"]; - 109 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 110 [label="Access variable R|/y|"]; - 111 [label="Smart cast: R|/y|"]; - 112 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 113 [label="Const: Int(1)"]; + 111 [label="Enter block"]; + 112 [label="Access variable R|/x|"]; + 113 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; 114 [label="Exit block"]; } 115 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 85 [label="Postponed exit from lambda"]; - 86 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 87 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 88 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 89 [label="Access variable R|/x|"]; - 90 [label="Smart cast: R|/x|"]; - 91 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 92 [label="Access variable R|/y|"]; - 93 [label="Smart cast: R|/y|"]; - 94 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 95 [label="Exit block"]; + 103 [label="Postponed exit from lambda"]; + 104 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; + 105 [label="Access variable R|/x|"]; + 106 [label="Smart cast: R|/x|"]; + 107 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 108 [label="Exit block"]; } - 96 [label="Exit function completedCallExactlyOnce" style="filled" fillcolor=red]; + 109 [label="Exit function basic" style="filled" fillcolor=red]; } - 76 -> {77}; - 77 -> {78}; - 78 -> {97 80}; - 78 -> {79} [style=dotted]; - 78 -> {97} [style=dashed]; - 79 -> {81} [color=red]; - 79 -> {80} [color=green]; - 80 -> {81}; - 81 -> {82}; - 82 -> {83}; - 83 -> {84}; - 84 -> {105 86}; - 84 -> {85} [style=dotted]; - 84 -> {105} [style=dashed]; - 85 -> {87} [color=red]; - 85 -> {86} [color=green]; - 86 -> {87}; - 87 -> {88}; - 88 -> {89}; - 89 -> {90}; - 90 -> {91}; - 91 -> {92}; - 92 -> {93}; - 93 -> {94}; - 94 -> {95}; - 95 -> {96}; - 97 -> {98}; - 98 -> {99}; - 99 -> {100}; 100 -> {101}; 101 -> {102}; - 102 -> {103}; + 102 -> {110 104}; + 102 -> {103} [style=dotted]; + 102 -> {110} [style=dashed]; 103 -> {104}; - 104 -> {79}; + 104 -> {105}; 105 -> {106}; 106 -> {107}; 107 -> {108}; 108 -> {109}; - 109 -> {110}; 110 -> {111}; 111 -> {112}; 112 -> {113}; 113 -> {114}; 114 -> {115}; - 115 -> {85}; + 115 -> {103}; - subgraph cluster_26 { + subgraph cluster_24 { color=red - 116 [label="Enter function completedCallAtLeastOnce" style="filled" fillcolor=red]; - subgraph cluster_27 { + 116 [label="Enter function completedCallExactlyOnce" style="filled" fillcolor=red]; + subgraph cluster_25 { color=blue 117 [label="Enter block"]; 118 [label="Postponed enter to lambda"]; - subgraph cluster_28 { + subgraph cluster_26 { color=blue 137 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_29 { + subgraph cluster_27 { color=blue 138 [label="Enter block"]; 139 [label="Access variable R|/y|"]; @@ -351,15 +275,15 @@ digraph flowFromInplaceLambda_kt { 144 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 119 [label="Postponed exit from lambda"]; - 120 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; + 120 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; 121 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 122 [label="Access variable R|/y|"]; 123 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; 124 [label="Postponed enter to lambda"]; - subgraph cluster_30 { + subgraph cluster_28 { color=blue 145 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_31 { + subgraph cluster_29 { color=blue 146 [label="Enter block"]; 147 [label="Access variable R|/x|"]; @@ -374,7 +298,7 @@ digraph flowFromInplaceLambda_kt { 155 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 125 [label="Postponed exit from lambda"]; - 126 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; + 126 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; 127 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; 128 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; 129 [label="Access variable R|/x|"]; @@ -385,7 +309,7 @@ digraph flowFromInplaceLambda_kt { 134 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; 135 [label="Exit block"]; } - 136 [label="Exit function completedCallAtLeastOnce" style="filled" fillcolor=red]; + 136 [label="Exit function completedCallExactlyOnce" style="filled" fillcolor=red]; } 116 -> {117}; 117 -> {118}; @@ -394,7 +318,6 @@ digraph flowFromInplaceLambda_kt { 118 -> {137} [style=dashed]; 119 -> {121} [color=red]; 119 -> {120} [color=green]; - 119 -> {118} [color=green style=dashed]; 120 -> {121}; 121 -> {122}; 122 -> {123}; @@ -404,7 +327,6 @@ digraph flowFromInplaceLambda_kt { 124 -> {145} [style=dashed]; 125 -> {127} [color=red]; 125 -> {126} [color=green]; - 125 -> {124} [color=green style=dashed]; 126 -> {127}; 127 -> {128}; 128 -> {129}; @@ -435,76 +357,82 @@ digraph flowFromInplaceLambda_kt { 154 -> {155}; 155 -> {125}; - subgraph cluster_32 { + subgraph cluster_30 { color=red - 156 [label="Enter function completedCallAtMostOnce" style="filled" fillcolor=red]; - subgraph cluster_33 { + 156 [label="Enter function completedCallAtLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_31 { color=blue 157 [label="Enter block"]; 158 [label="Postponed enter to lambda"]; - subgraph cluster_34 { + subgraph cluster_32 { color=blue - 176 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_35 { + 177 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_33 { color=blue - 177 [label="Enter block"]; - 178 [label="Access variable R|/y|"]; - 179 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 180 [label="Access variable R|/x|"]; - 181 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 182 [label="Exit block"]; + 178 [label="Enter block"]; + 179 [label="Access variable R|/y|"]; + 180 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 181 [label="Access variable R|/x|"]; + 182 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 183 [label="Exit block"]; } - 183 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 184 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 159 [label="Postponed exit from lambda"]; - 160 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 160 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; 161 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 162 [label="Access variable R|/y|"]; 163 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; 164 [label="Postponed enter to lambda"]; - subgraph cluster_36 { + subgraph cluster_34 { color=blue - 184 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_37 { + 185 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_35 { color=blue - 185 [label="Enter block"]; - 186 [label="Access variable R|/x|"]; - 187 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 188 [label="Access variable R|/y|"]; - 189 [label="Smart cast: R|/y|"]; - 190 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 191 [label="Const: Int(1)"]; - 192 [label="Exit block"]; + 186 [label="Enter block"]; + 187 [label="Access variable R|/x|"]; + 188 [label="Smart cast: R|/x|"]; + 189 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 190 [label="Access variable R|/y|"]; + 191 [label="Smart cast: R|/y|"]; + 192 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 193 [label="Const: Int(1)"]; + 194 [label="Exit block"]; } - 193 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 195 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 165 [label="Postponed exit from lambda"]; - 166 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 166 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; 167 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; 168 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; 169 [label="Access variable R|/x|"]; - 170 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 171 [label="Access variable R|/y|"]; - 172 [label="Smart cast: R|/y|"]; - 173 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 174 [label="Exit block"]; + 170 [label="Smart cast: R|/x|"]; + 171 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 172 [label="Access variable R|/y|"]; + 173 [label="Smart cast: R|/y|"]; + 174 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 175 [label="Exit block"]; } - 175 [label="Exit function completedCallAtMostOnce" style="filled" fillcolor=red]; + 176 [label="Exit function completedCallAtLeastOnce" style="filled" fillcolor=red]; } 156 -> {157}; 157 -> {158}; - 158 -> {159 176 160}; - 158 -> {176} [style=dashed]; + 158 -> {177 160}; + 158 -> {159} [style=dotted]; + 158 -> {177} [style=dashed]; 159 -> {161} [color=red]; 159 -> {160} [color=green]; + 159 -> {158} [color=green style=dashed]; 160 -> {161}; 161 -> {162}; 162 -> {163}; 163 -> {164}; - 164 -> {165 184 166}; - 164 -> {184} [style=dashed]; + 164 -> {185 166}; + 164 -> {165} [style=dotted]; + 164 -> {185} [style=dashed]; 165 -> {167} [color=red]; 165 -> {166} [color=green]; + 165 -> {164} [color=green style=dashed]; 166 -> {167}; 167 -> {168}; 168 -> {169}; @@ -514,15 +442,15 @@ digraph flowFromInplaceLambda_kt { 172 -> {173}; 173 -> {174}; 174 -> {175}; - 176 -> {177}; + 175 -> {176}; 177 -> {178}; 178 -> {179}; 179 -> {180}; 180 -> {181}; 181 -> {182}; 182 -> {183}; - 183 -> {159}; - 184 -> {185}; + 183 -> {184}; + 184 -> {159}; 185 -> {186}; 186 -> {187}; 187 -> {188}; @@ -531,82 +459,80 @@ digraph flowFromInplaceLambda_kt { 190 -> {191}; 191 -> {192}; 192 -> {193}; - 193 -> {165}; + 193 -> {194}; + 194 -> {195}; + 195 -> {165}; - subgraph cluster_38 { + subgraph cluster_36 { color=red - 194 [label="Enter function completedCallUnknown" style="filled" fillcolor=red]; - subgraph cluster_39 { + 196 [label="Enter function completedCallAtMostOnce" style="filled" fillcolor=red]; + subgraph cluster_37 { color=blue - 195 [label="Enter block"]; - 196 [label="Postponed enter to lambda"]; + 197 [label="Enter block"]; + 198 [label="Postponed enter to lambda"]; + subgraph cluster_38 { + color=blue + 216 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_39 { + color=blue + 217 [label="Enter block"]; + 218 [label="Access variable R|/y|"]; + 219 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 220 [label="Access variable R|/x|"]; + 221 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 222 [label="Exit block"]; + } + 223 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 199 [label="Postponed exit from lambda"]; + 200 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 201 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 202 [label="Access variable R|/y|"]; + 203 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 204 [label="Postponed enter to lambda"]; subgraph cluster_40 { color=blue - 214 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 224 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_41 { color=blue - 215 [label="Enter block"]; - 216 [label="Access variable R|/y|"]; - 217 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 218 [label="Access variable R|/x|"]; - 219 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 220 [label="Exit block"]; + 225 [label="Enter block"]; + 226 [label="Access variable R|/x|"]; + 227 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 228 [label="Access variable R|/y|"]; + 229 [label="Smart cast: R|/y|"]; + 230 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 231 [label="Const: Int(1)"]; + 232 [label="Exit block"]; } - 221 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 233 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 197 [label="Postponed exit from lambda"]; - 198 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 199 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 200 [label="Access variable R|/y|"]; - 201 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 202 [label="Postponed enter to lambda"]; - subgraph cluster_42 { - color=blue - 222 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_43 { - color=blue - 223 [label="Enter block"]; - 224 [label="Access variable R|/x|"]; - 225 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 226 [label="Access variable R|/y|"]; - 227 [label="Smart cast: R|/y|"]; - 228 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 229 [label="Const: Int(1)"]; - 230 [label="Exit block"]; - } - 231 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 203 [label="Postponed exit from lambda"]; - 204 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 205 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 206 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 207 [label="Access variable R|/x|"]; - 208 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 209 [label="Access variable R|/y|"]; - 210 [label="Smart cast: R|/y|"]; - 211 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 212 [label="Exit block"]; + 205 [label="Postponed exit from lambda"]; + 206 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 207 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 208 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 209 [label="Access variable R|/x|"]; + 210 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 211 [label="Access variable R|/y|"]; + 212 [label="Smart cast: R|/y|"]; + 213 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 214 [label="Exit block"]; } - 213 [label="Exit function completedCallUnknown" style="filled" fillcolor=red]; + 215 [label="Exit function completedCallAtMostOnce" style="filled" fillcolor=red]; } - 194 -> {195}; - 195 -> {196}; - 196 -> {197 214 198}; - 196 -> {214} [style=dashed]; - 197 -> {199} [color=red]; - 197 -> {198} [color=green]; - 197 -> {196} [color=green style=dashed]; - 198 -> {199}; - 199 -> {200}; + 196 -> {197}; + 197 -> {198}; + 198 -> {199 216 200}; + 198 -> {216} [style=dashed]; + 199 -> {201} [color=red]; + 199 -> {200} [color=green]; 200 -> {201}; 201 -> {202}; - 202 -> {203 222 204}; - 202 -> {222} [style=dashed]; - 203 -> {205} [color=red]; - 203 -> {204} [color=green]; - 203 -> {202} [color=green style=dashed]; - 204 -> {205}; - 205 -> {206}; + 202 -> {203}; + 203 -> {204}; + 204 -> {205 224 206}; + 204 -> {224} [style=dashed]; + 205 -> {207} [color=red]; + 205 -> {206} [color=green]; 206 -> {207}; 207 -> {208}; 208 -> {209}; @@ -614,16 +540,16 @@ digraph flowFromInplaceLambda_kt { 210 -> {211}; 211 -> {212}; 212 -> {213}; + 213 -> {214}; 214 -> {215}; - 215 -> {216}; 216 -> {217}; 217 -> {218}; 218 -> {219}; 219 -> {220}; 220 -> {221}; - 221 -> {197}; + 221 -> {222}; 222 -> {223}; - 223 -> {224}; + 223 -> {199}; 224 -> {225}; 225 -> {226}; 226 -> {227}; @@ -631,80 +557,82 @@ digraph flowFromInplaceLambda_kt { 228 -> {229}; 229 -> {230}; 230 -> {231}; - 231 -> {203}; + 231 -> {232}; + 232 -> {233}; + 233 -> {205}; - subgraph cluster_44 { + subgraph cluster_42 { color=red - 232 [label="Enter function completedCallNoContract" style="filled" fillcolor=red]; - subgraph cluster_45 { + 234 [label="Enter function completedCallUnknown" style="filled" fillcolor=red]; + subgraph cluster_43 { color=blue - 233 [label="Enter block"]; - 234 [label="Postponed enter to lambda"]; + 235 [label="Enter block"]; + 236 [label="Postponed enter to lambda"]; + subgraph cluster_44 { + color=blue + 254 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_45 { + color=blue + 255 [label="Enter block"]; + 256 [label="Access variable R|/y|"]; + 257 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 258 [label="Access variable R|/x|"]; + 259 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 260 [label="Exit block"]; + } + 261 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 237 [label="Postponed exit from lambda"]; + 238 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 239 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 240 [label="Access variable R|/y|"]; + 241 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 242 [label="Postponed enter to lambda"]; subgraph cluster_46 { color=blue - 252 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 262 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_47 { color=blue - 253 [label="Enter block"]; - 254 [label="Access variable R|/y|"]; - 255 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 256 [label="Access variable R|/x|"]; - 257 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 258 [label="Exit block"]; + 263 [label="Enter block"]; + 264 [label="Access variable R|/x|"]; + 265 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 266 [label="Access variable R|/y|"]; + 267 [label="Smart cast: R|/y|"]; + 268 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 269 [label="Const: Int(1)"]; + 270 [label="Exit block"]; } - 259 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 271 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 235 [label="Postponed exit from lambda"]; - 236 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; - 237 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 238 [label="Access variable R|/y|"]; - 239 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 240 [label="Postponed enter to lambda"]; - subgraph cluster_48 { - color=blue - 260 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_49 { - color=blue - 261 [label="Enter block"]; - 262 [label="Access variable R|/x|"]; - 263 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 264 [label="Access variable R|/y|"]; - 265 [label="Smart cast: R|/y|"]; - 266 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 267 [label="Const: Int(1)"]; - 268 [label="Exit block"]; - } - 269 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 241 [label="Postponed exit from lambda"]; - 242 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; - 243 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 244 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 245 [label="Access variable R|/x|"]; - 246 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 247 [label="Access variable R|/y|"]; - 248 [label="Smart cast: R|/y|"]; - 249 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 250 [label="Exit block"]; + 243 [label="Postponed exit from lambda"]; + 244 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 245 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 246 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 247 [label="Access variable R|/x|"]; + 248 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 249 [label="Access variable R|/y|"]; + 250 [label="Smart cast: R|/y|"]; + 251 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 252 [label="Exit block"]; } - 251 [label="Exit function completedCallNoContract" style="filled" fillcolor=red]; + 253 [label="Exit function completedCallUnknown" style="filled" fillcolor=red]; } - 232 -> {233}; - 233 -> {234}; - 234 -> {235 252 236}; - 234 -> {252} [style=dashed]; - 235 -> {237} [color=red]; - 235 -> {236} [color=green]; - 236 -> {237}; - 237 -> {238}; + 234 -> {235}; + 235 -> {236}; + 236 -> {237 254 238}; + 236 -> {254} [style=dashed]; + 237 -> {239} [color=red]; + 237 -> {238} [color=green]; + 237 -> {236} [color=green style=dashed]; 238 -> {239}; 239 -> {240}; - 240 -> {241 260 242}; - 240 -> {260} [style=dashed]; - 241 -> {243} [color=red]; - 241 -> {242} [color=green]; - 242 -> {243}; - 243 -> {244}; + 240 -> {241}; + 241 -> {242}; + 242 -> {243 262 244}; + 242 -> {262} [style=dashed]; + 243 -> {245} [color=red]; + 243 -> {244} [color=green]; + 243 -> {242} [color=green style=dashed]; 244 -> {245}; 245 -> {246}; 246 -> {247}; @@ -712,15 +640,16 @@ digraph flowFromInplaceLambda_kt { 248 -> {249}; 249 -> {250}; 250 -> {251}; + 251 -> {252}; 252 -> {253}; - 253 -> {254}; 254 -> {255}; 255 -> {256}; 256 -> {257}; 257 -> {258}; 258 -> {259}; + 259 -> {260}; 260 -> {261}; - 261 -> {262}; + 261 -> {237}; 262 -> {263}; 263 -> {264}; 264 -> {265}; @@ -728,95 +657,89 @@ digraph flowFromInplaceLambda_kt { 266 -> {267}; 267 -> {268}; 268 -> {269}; + 269 -> {270}; + 270 -> {271}; + 271 -> {243}; - subgraph cluster_50 { + subgraph cluster_48 { color=red - 270 [label="Enter function incompleteCallExactlyOnce" style="filled" fillcolor=red]; - subgraph cluster_51 { + 272 [label="Enter function completedCallNoContract" style="filled" fillcolor=red]; + subgraph cluster_49 { color=blue - 271 [label="Enter block"]; - 272 [label="Postponed enter to lambda"]; + 273 [label="Enter block"]; + 274 [label="Postponed enter to lambda"]; + subgraph cluster_50 { + color=blue + 292 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_51 { + color=blue + 293 [label="Enter block"]; + 294 [label="Access variable R|/y|"]; + 295 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 296 [label="Access variable R|/x|"]; + 297 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 298 [label="Exit block"]; + } + 299 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 275 [label="Postponed exit from lambda"]; + 276 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; + 277 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 278 [label="Access variable R|/y|"]; + 279 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 280 [label="Postponed enter to lambda"]; subgraph cluster_52 { color=blue - 289 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 300 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_53 { color=blue - 290 [label="Enter block"]; - 291 [label="Access variable R|/x|"]; - 292 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 293 [label="Access variable R|/y|"]; - 294 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 295 [label="Access variable R|/x|"]; - 296 [label="Smart cast: R|/x|"]; - 297 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 298 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 299 [label="Exit block"]; + 301 [label="Enter block"]; + 302 [label="Access variable R|/x|"]; + 303 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 304 [label="Access variable R|/y|"]; + 305 [label="Smart cast: R|/y|"]; + 306 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 307 [label="Const: Int(1)"]; + 308 [label="Exit block"]; } - 300 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 309 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 273 [label="Postponed exit from lambda"]; - 274 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 275 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 276 [label="Postponed enter to lambda"]; - subgraph cluster_54 { - color=blue - 301 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_55 { - color=blue - 302 [label="Enter block"]; - 303 [label="Access variable R|/y|"]; - 304 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 305 [label="Access variable R|/x|"]; - 306 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 307 [label="Access variable R|/y|"]; - 308 [label="Smart cast: R|/y|"]; - 309 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 310 [label="Const: Int(1)"]; - 311 [label="Exit block"]; - } - 312 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 277 [label="Postponed exit from lambda"]; - 278 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 279 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 280 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 281 [label="Access variable R|/x|"]; - 282 [label="Smart cast: R|/x|"]; - 283 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 284 [label="Access variable R|/y|"]; - 285 [label="Smart cast: R|/y|"]; - 286 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 287 [label="Exit block"]; + 281 [label="Postponed exit from lambda"]; + 282 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; + 283 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 284 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 285 [label="Access variable R|/x|"]; + 286 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 287 [label="Access variable R|/y|"]; + 288 [label="Smart cast: R|/y|"]; + 289 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 290 [label="Exit block"]; } - 288 [label="Exit function incompleteCallExactlyOnce" style="filled" fillcolor=red]; + 291 [label="Exit function completedCallNoContract" style="filled" fillcolor=red]; } - 270 -> {271}; - 271 -> {272}; - 272 -> {289 274}; - 272 -> {273} [style=dotted]; - 272 -> {289} [style=dashed]; - 273 -> {279} [color=red]; - 273 -> {274} [color=green]; - 274 -> {275}; - 275 -> {276}; - 276 -> {301 278}; - 276 -> {277} [style=dotted]; - 276 -> {301} [style=dashed]; - 277 -> {279} [color=red]; - 277 -> {278} [color=green]; + 272 -> {273}; + 273 -> {274}; + 274 -> {275 292 276}; + 274 -> {292} [style=dashed]; + 275 -> {277} [color=red]; + 275 -> {276} [color=green]; + 276 -> {277}; + 277 -> {278}; 278 -> {279}; 279 -> {280}; - 280 -> {281}; - 281 -> {282}; + 280 -> {281 300 282}; + 280 -> {300} [style=dashed]; + 281 -> {283} [color=red]; + 281 -> {282} [color=green]; 282 -> {283}; 283 -> {284}; 284 -> {285}; 285 -> {286}; 286 -> {287}; 287 -> {288}; + 288 -> {289}; 289 -> {290}; 290 -> {291}; - 291 -> {292}; 292 -> {293}; 293 -> {294}; 294 -> {295}; @@ -824,8 +747,7 @@ digraph flowFromInplaceLambda_kt { 296 -> {297}; 297 -> {298}; 298 -> {299}; - 299 -> {300}; - 300 -> {273}; + 300 -> {301}; 301 -> {302}; 302 -> {303}; 303 -> {304}; @@ -834,88 +756,85 @@ digraph flowFromInplaceLambda_kt { 306 -> {307}; 307 -> {308}; 308 -> {309}; - 309 -> {310}; - 310 -> {311}; - 311 -> {312}; - 312 -> {277}; - subgraph cluster_56 { + subgraph cluster_54 { color=red - 313 [label="Enter function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; - subgraph cluster_57 { + 310 [label="Enter function incompleteCallExactlyOnce" style="filled" fillcolor=red]; + subgraph cluster_55 { color=blue - 314 [label="Enter block"]; - 315 [label="Postponed enter to lambda"]; + 311 [label="Enter block"]; + 312 [label="Postponed enter to lambda"]; + subgraph cluster_56 { + color=blue + 329 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_57 { + color=blue + 330 [label="Enter block"]; + 331 [label="Access variable R|/x|"]; + 332 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 333 [label="Access variable R|/y|"]; + 334 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 335 [label="Access variable R|/x|"]; + 336 [label="Smart cast: R|/x|"]; + 337 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 338 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 339 [label="Exit block"]; + } + 340 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 313 [label="Postponed exit from lambda"]; + 314 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; + 315 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 316 [label="Postponed enter to lambda"]; subgraph cluster_58 { color=blue - 332 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 341 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_59 { color=blue - 333 [label="Enter block"]; - 334 [label="Access variable R|/x|"]; - 335 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 336 [label="Access variable R|/y|"]; - 337 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 338 [label="Access variable R|/x|"]; - 339 [label="Smart cast: R|/x|"]; - 340 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 341 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 342 [label="Exit block"]; + 342 [label="Enter block"]; + 343 [label="Access variable R|/y|"]; + 344 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 345 [label="Access variable R|/x|"]; + 346 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 347 [label="Access variable R|/y|"]; + 348 [label="Smart cast: R|/y|"]; + 349 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 350 [label="Const: Int(1)"]; + 351 [label="Exit block"]; } - 343 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 352 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 316 [label="Postponed exit from lambda"]; - 317 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; - 318 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 319 [label="Postponed enter to lambda"]; - subgraph cluster_60 { - color=blue - 344 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_61 { - color=blue - 345 [label="Enter block"]; - 346 [label="Access variable R|/y|"]; - 347 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 348 [label="Access variable R|/x|"]; - 349 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 350 [label="Access variable R|/y|"]; - 351 [label="Smart cast: R|/y|"]; - 352 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 353 [label="Const: Int(1)"]; - 354 [label="Exit block"]; - } - 355 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 320 [label="Postponed exit from lambda"]; - 321 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; - 322 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 323 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 324 [label="Access variable R|/x|"]; - 325 [label="Smart cast: R|/x|"]; - 326 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 327 [label="Access variable R|/y|"]; - 328 [label="Smart cast: R|/y|"]; - 329 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 330 [label="Exit block"]; + 317 [label="Postponed exit from lambda"]; + 318 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; + 319 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 320 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 321 [label="Access variable R|/x|"]; + 322 [label="Smart cast: R|/x|"]; + 323 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 324 [label="Access variable R|/y|"]; + 325 [label="Smart cast: R|/y|"]; + 326 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 327 [label="Exit block"]; } - 331 [label="Exit function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; + 328 [label="Exit function incompleteCallExactlyOnce" style="filled" fillcolor=red]; } - 313 -> {314}; + 310 -> {311}; + 311 -> {312}; + 312 -> {329 314}; + 312 -> {313} [style=dotted]; + 312 -> {329} [style=dashed]; + 313 -> {319} [color=red]; + 313 -> {314} [color=green]; 314 -> {315}; - 315 -> {332 317}; - 315 -> {316} [style=dotted]; - 315 -> {332} [style=dashed]; - 316 -> {322} [color=red]; - 316 -> {317} [color=green]; - 316 -> {315} [color=green style=dashed]; - 317 -> {318}; + 315 -> {316}; + 316 -> {341 318}; + 316 -> {317} [style=dotted]; + 316 -> {341} [style=dashed]; + 317 -> {319} [color=red]; + 317 -> {318} [color=green]; 318 -> {319}; - 319 -> {344 321}; - 319 -> {320} [style=dotted]; - 319 -> {344} [style=dashed]; - 320 -> {322} [color=red]; - 320 -> {321} [color=green]; - 320 -> {319} [color=green style=dashed]; + 319 -> {320}; + 320 -> {321}; 321 -> {322}; 322 -> {323}; 323 -> {324}; @@ -923,9 +842,9 @@ digraph flowFromInplaceLambda_kt { 325 -> {326}; 326 -> {327}; 327 -> {328}; - 328 -> {329}; 329 -> {330}; 330 -> {331}; + 331 -> {332}; 332 -> {333}; 333 -> {334}; 334 -> {335}; @@ -934,10 +853,10 @@ digraph flowFromInplaceLambda_kt { 337 -> {338}; 338 -> {339}; 339 -> {340}; - 340 -> {341}; + 340 -> {313}; 341 -> {342}; 342 -> {343}; - 343 -> {316}; + 343 -> {344}; 344 -> {345}; 345 -> {346}; 346 -> {347}; @@ -946,82 +865,88 @@ digraph flowFromInplaceLambda_kt { 349 -> {350}; 350 -> {351}; 351 -> {352}; - 352 -> {353}; - 353 -> {354}; - 354 -> {355}; - 355 -> {320}; + 352 -> {317}; - subgraph cluster_62 { + subgraph cluster_60 { color=red - 356 [label="Enter function incompleteCallAtMostOnce" style="filled" fillcolor=red]; - subgraph cluster_63 { + 353 [label="Enter function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_61 { color=blue - 357 [label="Enter block"]; - 358 [label="Postponed enter to lambda"]; + 354 [label="Enter block"]; + 355 [label="Postponed enter to lambda"]; + subgraph cluster_62 { + color=blue + 372 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_63 { + color=blue + 373 [label="Enter block"]; + 374 [label="Access variable R|/x|"]; + 375 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 376 [label="Access variable R|/y|"]; + 377 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 378 [label="Access variable R|/x|"]; + 379 [label="Smart cast: R|/x|"]; + 380 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 381 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 382 [label="Exit block"]; + } + 383 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 356 [label="Postponed exit from lambda"]; + 357 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; + 358 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 359 [label="Postponed enter to lambda"]; subgraph cluster_64 { color=blue - 373 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 384 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_65 { color=blue - 374 [label="Enter block"]; - 375 [label="Access variable R|/x|"]; - 376 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 377 [label="Access variable R|/y|"]; - 378 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 379 [label="Access variable R|/x|"]; - 380 [label="Smart cast: R|/x|"]; - 381 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 382 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 383 [label="Exit block"]; + 385 [label="Enter block"]; + 386 [label="Access variable R|/y|"]; + 387 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 388 [label="Access variable R|/x|"]; + 389 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 390 [label="Access variable R|/y|"]; + 391 [label="Smart cast: R|/y|"]; + 392 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 393 [label="Const: Int(1)"]; + 394 [label="Exit block"]; } - 384 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 395 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 359 [label="Postponed exit from lambda"]; - 360 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; - 361 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 362 [label="Postponed enter to lambda"]; - subgraph cluster_66 { - color=blue - 385 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_67 { - color=blue - 386 [label="Enter block"]; - 387 [label="Access variable R|/y|"]; - 388 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 389 [label="Access variable R|/x|"]; - 390 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 391 [label="Access variable R|/y|"]; - 392 [label="Smart cast: R|/y|"]; - 393 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 394 [label="Const: Int(1)"]; - 395 [label="Exit block"]; - } - 396 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 363 [label="Postponed exit from lambda"]; - 364 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; - 365 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 366 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 367 [label="Access variable R|/x|"]; - 368 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 369 [label="Access variable R|/y|"]; - 370 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 371 [label="Exit block"]; + 360 [label="Postponed exit from lambda"]; + 361 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; + 362 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 363 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 364 [label="Access variable R|/x|"]; + 365 [label="Smart cast: R|/x|"]; + 366 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 367 [label="Access variable R|/y|"]; + 368 [label="Smart cast: R|/y|"]; + 369 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 370 [label="Exit block"]; } - 372 [label="Exit function incompleteCallAtMostOnce" style="filled" fillcolor=red]; + 371 [label="Exit function incompleteCallAtLeastOnce" style="filled" fillcolor=red]; } - 356 -> {357}; + 353 -> {354}; + 354 -> {355}; + 355 -> {372 357}; + 355 -> {356} [style=dotted]; + 355 -> {372} [style=dashed]; + 356 -> {362} [color=red]; + 356 -> {357} [color=green]; + 356 -> {355} [color=green style=dashed]; 357 -> {358}; - 358 -> {359 373 360}; - 358 -> {373} [style=dashed]; - 359 -> {365} [color=red]; - 359 -> {360} [color=green]; - 360 -> {361}; + 358 -> {359}; + 359 -> {384 361}; + 359 -> {360} [style=dotted]; + 359 -> {384} [style=dashed]; + 360 -> {362} [color=red]; + 360 -> {361} [color=green]; + 360 -> {359} [color=green style=dashed]; 361 -> {362}; - 362 -> {363 385 364}; - 362 -> {385} [style=dashed]; - 363 -> {365} [color=red]; - 363 -> {364} [color=green]; + 362 -> {363}; + 363 -> {364}; 364 -> {365}; 365 -> {366}; 366 -> {367}; @@ -1029,7 +954,7 @@ digraph flowFromInplaceLambda_kt { 368 -> {369}; 369 -> {370}; 370 -> {371}; - 371 -> {372}; + 372 -> {373}; 373 -> {374}; 374 -> {375}; 375 -> {376}; @@ -1040,8 +965,8 @@ digraph flowFromInplaceLambda_kt { 380 -> {381}; 381 -> {382}; 382 -> {383}; - 383 -> {384}; - 384 -> {359}; + 383 -> {356}; + 384 -> {385}; 385 -> {386}; 386 -> {387}; 387 -> {388}; @@ -1052,82 +977,80 @@ digraph flowFromInplaceLambda_kt { 392 -> {393}; 393 -> {394}; 394 -> {395}; - 395 -> {396}; - 396 -> {363}; + 395 -> {360}; - subgraph cluster_68 { + subgraph cluster_66 { color=red - 397 [label="Enter function incompleteCallUnknown" style="filled" fillcolor=red]; - subgraph cluster_69 { + 396 [label="Enter function incompleteCallAtMostOnce" style="filled" fillcolor=red]; + subgraph cluster_67 { color=blue - 398 [label="Enter block"]; - 399 [label="Postponed enter to lambda"]; + 397 [label="Enter block"]; + 398 [label="Postponed enter to lambda"]; + subgraph cluster_68 { + color=blue + 413 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_69 { + color=blue + 414 [label="Enter block"]; + 415 [label="Access variable R|/x|"]; + 416 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 417 [label="Access variable R|/y|"]; + 418 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 419 [label="Access variable R|/x|"]; + 420 [label="Smart cast: R|/x|"]; + 421 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 422 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 423 [label="Exit block"]; + } + 424 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 399 [label="Postponed exit from lambda"]; + 400 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 401 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 402 [label="Postponed enter to lambda"]; subgraph cluster_70 { color=blue - 414 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 425 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_71 { color=blue - 415 [label="Enter block"]; - 416 [label="Access variable R|/x|"]; - 417 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 418 [label="Access variable R|/y|"]; - 419 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 420 [label="Access variable R|/x|"]; - 421 [label="Smart cast: R|/x|"]; - 422 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 423 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 424 [label="Exit block"]; + 426 [label="Enter block"]; + 427 [label="Access variable R|/y|"]; + 428 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 429 [label="Access variable R|/x|"]; + 430 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 431 [label="Access variable R|/y|"]; + 432 [label="Smart cast: R|/y|"]; + 433 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 434 [label="Const: Int(1)"]; + 435 [label="Exit block"]; } - 425 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 436 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 400 [label="Postponed exit from lambda"]; - 401 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 402 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 403 [label="Postponed enter to lambda"]; - subgraph cluster_72 { - color=blue - 426 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_73 { - color=blue - 427 [label="Enter block"]; - 428 [label="Access variable R|/y|"]; - 429 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 430 [label="Access variable R|/x|"]; - 431 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 432 [label="Access variable R|/y|"]; - 433 [label="Smart cast: R|/y|"]; - 434 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 435 [label="Const: Int(1)"]; - 436 [label="Exit block"]; - } - 437 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 404 [label="Postponed exit from lambda"]; - 405 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 406 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 407 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 408 [label="Access variable R|/x|"]; - 409 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 410 [label="Access variable R|/y|"]; - 411 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 412 [label="Exit block"]; + 403 [label="Postponed exit from lambda"]; + 404 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 405 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 406 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 407 [label="Access variable R|/x|"]; + 408 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 409 [label="Access variable R|/y|"]; + 410 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 411 [label="Exit block"]; } - 413 [label="Exit function incompleteCallUnknown" style="filled" fillcolor=red]; + 412 [label="Exit function incompleteCallAtMostOnce" style="filled" fillcolor=red]; } + 396 -> {397}; 397 -> {398}; - 398 -> {399}; - 399 -> {400 414 401}; - 399 -> {414} [style=dashed]; - 400 -> {406} [color=red]; - 400 -> {401} [color=green]; - 400 -> {399} [color=green style=dashed]; + 398 -> {399 413 400}; + 398 -> {413} [style=dashed]; + 399 -> {405} [color=red]; + 399 -> {400} [color=green]; + 400 -> {401}; 401 -> {402}; - 402 -> {403}; - 403 -> {404 426 405}; - 403 -> {426} [style=dashed]; - 404 -> {406} [color=red]; - 404 -> {405} [color=green]; - 404 -> {403} [color=green style=dashed]; + 402 -> {403 425 404}; + 402 -> {425} [style=dashed]; + 403 -> {405} [color=red]; + 403 -> {404} [color=green]; + 404 -> {405}; 405 -> {406}; 406 -> {407}; 407 -> {408}; @@ -1135,7 +1058,7 @@ digraph flowFromInplaceLambda_kt { 409 -> {410}; 410 -> {411}; 411 -> {412}; - 412 -> {413}; + 413 -> {414}; 414 -> {415}; 415 -> {416}; 416 -> {417}; @@ -1146,8 +1069,8 @@ digraph flowFromInplaceLambda_kt { 421 -> {422}; 422 -> {423}; 423 -> {424}; - 424 -> {425}; - 425 -> {400}; + 424 -> {399}; + 425 -> {426}; 426 -> {427}; 427 -> {428}; 428 -> {429}; @@ -1158,80 +1081,82 @@ digraph flowFromInplaceLambda_kt { 433 -> {434}; 434 -> {435}; 435 -> {436}; - 436 -> {437}; - 437 -> {404}; + 436 -> {403}; - subgraph cluster_74 { + subgraph cluster_72 { color=red - 438 [label="Enter function incompleteCallNoContract" style="filled" fillcolor=red]; - subgraph cluster_75 { + 437 [label="Enter function incompleteCallUnknown" style="filled" fillcolor=red]; + subgraph cluster_73 { color=blue - 439 [label="Enter block"]; - 440 [label="Postponed enter to lambda"]; + 438 [label="Enter block"]; + 439 [label="Postponed enter to lambda"]; + subgraph cluster_74 { + color=blue + 454 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_75 { + color=blue + 455 [label="Enter block"]; + 456 [label="Access variable R|/x|"]; + 457 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 458 [label="Access variable R|/y|"]; + 459 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 460 [label="Access variable R|/x|"]; + 461 [label="Smart cast: R|/x|"]; + 462 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 463 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 464 [label="Exit block"]; + } + 465 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 440 [label="Postponed exit from lambda"]; + 441 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 442 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 443 [label="Postponed enter to lambda"]; subgraph cluster_76 { color=blue - 455 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 466 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_77 { color=blue - 456 [label="Enter block"]; - 457 [label="Access variable R|/x|"]; - 458 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 459 [label="Access variable R|/y|"]; - 460 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 461 [label="Access variable R|/x|"]; - 462 [label="Smart cast: R|/x|"]; - 463 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 464 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 465 [label="Exit block"]; + 467 [label="Enter block"]; + 468 [label="Access variable R|/y|"]; + 469 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 470 [label="Access variable R|/x|"]; + 471 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 472 [label="Access variable R|/y|"]; + 473 [label="Smart cast: R|/y|"]; + 474 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 475 [label="Const: Int(1)"]; + 476 [label="Exit block"]; } - 466 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 477 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 441 [label="Postponed exit from lambda"]; - 442 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; - 443 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 444 [label="Postponed enter to lambda"]; - subgraph cluster_78 { - color=blue - 467 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_79 { - color=blue - 468 [label="Enter block"]; - 469 [label="Access variable R|/y|"]; - 470 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; - 471 [label="Access variable R|/x|"]; - 472 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 473 [label="Access variable R|/y|"]; - 474 [label="Smart cast: R|/y|"]; - 475 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 476 [label="Const: Int(1)"]; - 477 [label="Exit block"]; - } - 478 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 445 [label="Postponed exit from lambda"]; - 446 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; - 447 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 448 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 449 [label="Access variable R|/x|"]; - 450 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 451 [label="Access variable R|/y|"]; - 452 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; - 453 [label="Exit block"]; + 444 [label="Postponed exit from lambda"]; + 445 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 446 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 447 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 448 [label="Access variable R|/x|"]; + 449 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 450 [label="Access variable R|/y|"]; + 451 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 452 [label="Exit block"]; } - 454 [label="Exit function incompleteCallNoContract" style="filled" fillcolor=red]; + 453 [label="Exit function incompleteCallUnknown" style="filled" fillcolor=red]; } + 437 -> {438}; 438 -> {439}; - 439 -> {440}; - 440 -> {441 455 442}; - 440 -> {455} [style=dashed]; - 441 -> {447} [color=red]; - 441 -> {442} [color=green]; + 439 -> {440 454 441}; + 439 -> {454} [style=dashed]; + 440 -> {446} [color=red]; + 440 -> {441} [color=green]; + 440 -> {439} [color=green style=dashed]; + 441 -> {442}; 442 -> {443}; - 443 -> {444}; - 444 -> {445 467 446}; - 444 -> {467} [style=dashed]; - 445 -> {447} [color=red]; - 445 -> {446} [color=green]; + 443 -> {444 466 445}; + 443 -> {466} [style=dashed]; + 444 -> {446} [color=red]; + 444 -> {445} [color=green]; + 444 -> {443} [color=green style=dashed]; + 445 -> {446}; 446 -> {447}; 447 -> {448}; 448 -> {449}; @@ -1239,7 +1164,7 @@ digraph flowFromInplaceLambda_kt { 450 -> {451}; 451 -> {452}; 452 -> {453}; - 453 -> {454}; + 454 -> {455}; 455 -> {456}; 456 -> {457}; 457 -> {458}; @@ -1250,7 +1175,8 @@ digraph flowFromInplaceLambda_kt { 462 -> {463}; 463 -> {464}; 464 -> {465}; - 465 -> {466}; + 465 -> {440}; + 466 -> {467}; 467 -> {468}; 468 -> {469}; 469 -> {470}; @@ -1261,61 +1187,77 @@ digraph flowFromInplaceLambda_kt { 474 -> {475}; 475 -> {476}; 476 -> {477}; - 477 -> {478}; + 477 -> {444}; - subgraph cluster_80 { + subgraph cluster_78 { color=red - 479 [label="Enter function expectedType" style="filled" fillcolor=red]; - subgraph cluster_81 { + 478 [label="Enter function incompleteCallNoContract" style="filled" fillcolor=red]; + subgraph cluster_79 { color=blue - 480 [label="Enter block"]; - 481 [label="Postponed enter to lambda"]; + 479 [label="Enter block"]; + 480 [label="Postponed enter to lambda"]; + subgraph cluster_80 { + color=blue + 495 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_81 { + color=blue + 496 [label="Enter block"]; + 497 [label="Access variable R|/x|"]; + 498 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 499 [label="Access variable R|/y|"]; + 500 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 501 [label="Access variable R|/x|"]; + 502 [label="Smart cast: R|/x|"]; + 503 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 504 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 505 [label="Exit block"]; + } + 506 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 481 [label="Postponed exit from lambda"]; + 482 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; + 483 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 484 [label="Postponed enter to lambda"]; subgraph cluster_82 { color=blue - 493 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 507 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_83 { color=blue - 494 [label="Enter block"]; - 495 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 496 [label="Exit block"]; + 508 [label="Enter block"]; + 509 [label="Access variable R|/y|"]; + 510 [label="Type operator: (R|/y| as R|kotlin/Int|)"]; + 511 [label="Access variable R|/x|"]; + 512 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 513 [label="Access variable R|/y|"]; + 514 [label="Smart cast: R|/y|"]; + 515 [label="Function call: R|/y|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 516 [label="Const: Int(1)"]; + 517 [label="Exit block"]; } - 497 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 482 [label="Postponed exit from lambda"]; - 483 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 484 [label="Postponed enter to lambda"]; - subgraph cluster_84 { - color=blue - 498 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_85 { - color=blue - 499 [label="Enter block"]; - 500 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 501 [label="Exit block"]; - } - 502 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 518 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 485 [label="Postponed exit from lambda"]; - 486 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 486 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; 487 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; - 488 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 488 [label="Function call: R|/select|(...).R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; 489 [label="Access variable R|/x|"]; - 490 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 491 [label="Exit block"]; + 490 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 491 [label="Access variable R|/y|"]; + 492 [label="Function call: R|/y|.#()" style="filled" fillcolor=yellow]; + 493 [label="Exit block"]; } - 492 [label="Exit function expectedType" style="filled" fillcolor=red]; + 494 [label="Exit function incompleteCallNoContract" style="filled" fillcolor=red]; } + 478 -> {479}; 479 -> {480}; - 480 -> {481}; - 481 -> {493 483}; - 481 -> {482} [style=dotted]; - 481 -> {493} [style=dashed]; - 482 -> {487} [color=red]; - 482 -> {483} [color=green]; + 480 -> {481 495 482}; + 480 -> {495} [style=dashed]; + 481 -> {487} [color=red]; + 481 -> {482} [color=green]; + 482 -> {483}; 483 -> {484}; - 484 -> {498 486}; - 484 -> {485} [style=dotted]; - 484 -> {498} [style=dashed]; + 484 -> {485 507 486}; + 484 -> {507} [style=dashed]; 485 -> {487} [color=red]; 485 -> {486} [color=green]; 486 -> {487}; @@ -1324,83 +1266,169 @@ digraph flowFromInplaceLambda_kt { 489 -> {490}; 490 -> {491}; 491 -> {492}; + 492 -> {493}; 493 -> {494}; - 494 -> {495}; 495 -> {496}; 496 -> {497}; - 497 -> {482}; + 497 -> {498}; 498 -> {499}; 499 -> {500}; 500 -> {501}; 501 -> {502}; - 502 -> {485}; - - subgraph cluster_86 { - color=red - 503 [label="Enter function expectedTypeNested" style="filled" fillcolor=red]; - subgraph cluster_87 { - color=blue - 504 [label="Enter block"]; - 505 [label="Postponed enter to lambda"]; - subgraph cluster_88 { - color=blue - 514 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_89 { - color=blue - 515 [label="Enter block"]; - 516 [label="Postponed enter to lambda"]; - subgraph cluster_90 { - color=blue - 521 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_91 { - color=blue - 522 [label="Enter block"]; - 523 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; - 524 [label="Exit block"]; - } - 525 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 517 [label="Postponed exit from lambda"]; - 518 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 519 [label="Exit block"]; - } - 520 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 506 [label="Postponed exit from lambda"]; - 507 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; - 508 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; - 509 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 510 [label="Access variable R|/x|"]; - 511 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 512 [label="Exit block"]; - } - 513 [label="Exit function expectedTypeNested" style="filled" fillcolor=red]; - } + 502 -> {503}; 503 -> {504}; 504 -> {505}; - 505 -> {506 514 507}; - 505 -> {514} [style=dashed]; - 506 -> {508} [color=red]; - 506 -> {507} [color=green]; + 505 -> {506}; 507 -> {508}; 508 -> {509}; 509 -> {510}; 510 -> {511}; 511 -> {512}; 512 -> {513}; + 513 -> {514}; 514 -> {515}; 515 -> {516}; - 516 -> {521 518}; - 516 -> {517} [style=dotted]; - 516 -> {521} [style=dashed]; - 517 -> {508} [color=red]; - 517 -> {518} [color=green]; - 518 -> {519}; + 516 -> {517}; + 517 -> {518}; + + subgraph cluster_84 { + color=red + 519 [label="Enter function expectedType" style="filled" fillcolor=red]; + subgraph cluster_85 { + color=blue + 520 [label="Enter block"]; + 521 [label="Postponed enter to lambda"]; + subgraph cluster_86 { + color=blue + 533 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_87 { + color=blue + 534 [label="Enter block"]; + 535 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 536 [label="Exit block"]; + } + 537 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 522 [label="Postponed exit from lambda"]; + 523 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 524 [label="Postponed enter to lambda"]; + subgraph cluster_88 { + color=blue + 538 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_89 { + color=blue + 539 [label="Enter block"]; + 540 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 541 [label="Exit block"]; + } + 542 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 525 [label="Postponed exit from lambda"]; + 526 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 527 [label="Function call: R|/select|(...)" style="filled" fillcolor=yellow]; + 528 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 529 [label="Access variable R|/x|"]; + 530 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 531 [label="Exit block"]; + } + 532 [label="Exit function expectedType" style="filled" fillcolor=red]; + } 519 -> {520}; - 521 -> {522}; - 522 -> {523}; + 520 -> {521}; + 521 -> {533 523}; + 521 -> {522} [style=dotted]; + 521 -> {533} [style=dashed]; + 522 -> {527} [color=red]; + 522 -> {523} [color=green]; 523 -> {524}; - 524 -> {525}; - 525 -> {517}; + 524 -> {538 526}; + 524 -> {525} [style=dotted]; + 524 -> {538} [style=dashed]; + 525 -> {527} [color=red]; + 525 -> {526} [color=green]; + 526 -> {527}; + 527 -> {528}; + 528 -> {529}; + 529 -> {530}; + 530 -> {531}; + 531 -> {532}; + 533 -> {534}; + 534 -> {535}; + 535 -> {536}; + 536 -> {537}; + 537 -> {522}; + 538 -> {539}; + 539 -> {540}; + 540 -> {541}; + 541 -> {542}; + 542 -> {525}; + + subgraph cluster_90 { + color=red + 543 [label="Enter function expectedTypeNested" style="filled" fillcolor=red]; + subgraph cluster_91 { + color=blue + 544 [label="Enter block"]; + 545 [label="Postponed enter to lambda"]; + subgraph cluster_92 { + color=blue + 554 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_93 { + color=blue + 555 [label="Enter block"]; + 556 [label="Postponed enter to lambda"]; + subgraph cluster_94 { + color=blue + 561 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_95 { + color=blue + 562 [label="Enter block"]; + 563 [label="Function call: R|/materialize|()" style="filled" fillcolor=yellow]; + 564 [label="Exit block"]; + } + 565 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 557 [label="Postponed exit from lambda"]; + 558 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 559 [label="Exit block"]; + } + 560 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 546 [label="Postponed exit from lambda"]; + 547 [label="Function call: R|/noContract|(...)" style="filled" fillcolor=yellow]; + 548 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 549 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 550 [label="Access variable R|/x|"]; + 551 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 552 [label="Exit block"]; + } + 553 [label="Exit function expectedTypeNested" style="filled" fillcolor=red]; + } + 543 -> {544}; + 544 -> {545}; + 545 -> {546 554 547}; + 545 -> {554} [style=dashed]; + 546 -> {548} [color=red]; + 546 -> {547} [color=green]; + 547 -> {548}; + 548 -> {549}; + 549 -> {550}; + 550 -> {551}; + 551 -> {552}; + 552 -> {553}; + 554 -> {555}; + 555 -> {556}; + 556 -> {561 558}; + 556 -> {557} [style=dotted]; + 556 -> {561} [style=dashed]; + 557 -> {548} [color=red]; + 557 -> {558} [color=green]; + 558 -> {559}; + 559 -> {560}; + 561 -> {562}; + 562 -> {563}; + 563 -> {564}; + 564 -> {565}; + 565 -> {557}; } 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 3b086a96dd4..42cebb41d84 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.fir.txt @@ -5,7 +5,13 @@ FILE: flowFromInplaceLambda.kt CallsInPlace(x, UNKNOWN) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.UNKNOWN|) + } + ) + } + ^unknown R|/x|.R|SubstitutionOverride|() } public final fun atLeastOnce(x: R|() -> T|): R|T| @@ -14,7 +20,13 @@ FILE: flowFromInplaceLambda.kt CallsInPlace(x, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + ^atLeastOnce R|/x|.R|SubstitutionOverride|() } public final fun exactlyOnce(x: R|() -> T|): R|T| @@ -23,7 +35,13 @@ FILE: flowFromInplaceLambda.kt CallsInPlace(x, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + ^exactlyOnce R|/x|.R|SubstitutionOverride|() } public final fun atMostOnce(x: R|() -> T|): R|T| @@ -32,7 +50,13 @@ FILE: flowFromInplaceLambda.kt CallsInPlace(x, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + ^atMostOnce R|/x|.R|SubstitutionOverride|() } public final fun noContract(x: R|() -> T|): R|T| { diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt index 6b35a604d9a..8efba38ce7a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.kt @@ -1,4 +1,5 @@ // !DUMP_CFG +// !OPT_IN: kotlin.contracts.ExperimentalContracts import kotlin.contracts.* diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot index 8d9674908cf..44a776dd7be 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.dot @@ -9,350 +9,262 @@ digraph flowFromInplaceLambda3_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Exit block"]; } - 4 [label="Exit function unknown" style="filled" fillcolor=red]; + 6 [label="Exit function unknown" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; - - subgraph cluster_2 { - color=red - 5 [label="Enter function atLeastOnce" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 6 [label="Enter block"]; - 7 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 8 [label="Exit block"]; - } - 9 [label="Exit function atLeastOnce" style="filled" fillcolor=red]; - } + 4 -> {5}; 5 -> {6}; - 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - subgraph cluster_4 { + subgraph cluster_3 { color=red - 10 [label="Enter function exactlyOnce" style="filled" fillcolor=red]; - subgraph cluster_5 { - color=blue - 11 [label="Enter block"]; - 12 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 13 [label="Exit block"]; - } - 14 [label="Exit function exactlyOnce" style="filled" fillcolor=red]; - } - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {14}; - - subgraph cluster_6 { - color=red - 15 [label="Enter function atMostOnce" style="filled" fillcolor=red]; - subgraph cluster_7 { + 15 [label="Enter function atLeastOnce" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue 16 [label="Enter block"]; - 17 [label="Exit block"]; + subgraph cluster_5 { + color=blue + 17 [label="Enter block"]; + 18 [label="Exit block"]; + } + 19 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 18 [label="Exit function atMostOnce" style="filled" fillcolor=red]; + 21 [label="Exit function atLeastOnce" style="filled" fillcolor=red]; } 15 -> {16}; 16 -> {17}; 17 -> {18}; - - subgraph cluster_8 { - color=red - 19 [label="Enter function test1" style="filled" fillcolor=red]; - subgraph cluster_9 { - color=blue - 20 [label="Enter block"]; - 21 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 22 [label="Const: String()"]; - 23 [label="Assignment: R|/x|"]; - 24 [label="Access variable R|/x|"]; - 25 [label="Smart cast: R|/x|"]; - 26 [label="Access variable R|kotlin/String.length|"]; - 27 [label="Postponed enter to lambda"]; - subgraph cluster_10 { - color=blue - 38 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_11 { - color=blue - 39 [label="Enter block"]; - 40 [label="Const: Int(1)"]; - 41 [label="Assignment: R|/x|"]; - 42 [label="Exit block"]; - } - 43 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 28 [label="Postponed exit from lambda"]; - 29 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 30 [label="Access variable R|/x|"]; - 31 [label="Smart cast: R|/x|"]; - 32 [label="Access variable #"]; - 33 [label="Access variable R|/x|"]; - 34 [label="Smart cast: R|/x|"]; - 35 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 36 [label="Exit block"]; - } - 37 [label="Exit function test1" style="filled" fillcolor=red]; - } + 18 -> {19}; 19 -> {20}; 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {27}; - 27 -> {28 38 29}; - 27 -> {38} [style=dashed]; - 28 -> {29}; - 28 -> {27} [color=green style=dashed]; - 29 -> {30}; + + subgraph cluster_6 { + color=red + 30 [label="Enter function exactlyOnce" style="filled" fillcolor=red]; + subgraph cluster_7 { + color=blue + 31 [label="Enter block"]; + subgraph cluster_8 { + color=blue + 32 [label="Enter block"]; + 33 [label="Exit block"]; + } + 34 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 35 [label="Exit block"]; + } + 36 [label="Exit function exactlyOnce" style="filled" fillcolor=red]; + } 30 -> {31}; 31 -> {32}; 32 -> {33}; 33 -> {34}; 34 -> {35}; 35 -> {36}; - 36 -> {37}; - 38 -> {39}; - 39 -> {40}; - 40 -> {41}; - 41 -> {42}; - 42 -> {43}; - 43 -> {28}; - subgraph cluster_12 { + subgraph cluster_9 { color=red - 44 [label="Enter function test1m" style="filled" fillcolor=red]; - subgraph cluster_13 { + 45 [label="Enter function atMostOnce" style="filled" fillcolor=red]; + subgraph cluster_10 { color=blue - 45 [label="Enter block"]; - 46 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 47 [label="Const: String()"]; - 48 [label="Assignment: R|/x|"]; - 49 [label="Access variable R|/x|"]; - 50 [label="Smart cast: R|/x|"]; - 51 [label="Access variable R|kotlin/String.length|"]; - 52 [label="Postponed enter to lambda"]; - subgraph cluster_14 { + 46 [label="Enter block"]; + subgraph cluster_11 { color=blue - 60 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_15 { - color=blue - 61 [label="Enter block"]; - 62 [label="Const: String()"]; - 63 [label="Assignment: R|/x|"]; - 64 [label="Exit block"]; - } - 65 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 47 [label="Enter block"]; + 48 [label="Exit block"]; } - 53 [label="Postponed exit from lambda"]; - 54 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; - 55 [label="Access variable R|/x|"]; - 56 [label="Smart cast: R|/x|"]; - 57 [label="Access variable R|kotlin/String.length|"]; - 58 [label="Exit block"]; + 49 [label="Exit block"]; } - 59 [label="Exit function test1m" style="filled" fillcolor=red]; + 50 [label="Exit function atMostOnce" style="filled" fillcolor=red]; } - 44 -> {45}; 45 -> {46}; 46 -> {47}; 47 -> {48}; 48 -> {49}; 49 -> {50}; - 50 -> {51}; - 51 -> {52}; - 52 -> {53 60 54}; - 52 -> {60} [style=dashed]; - 53 -> {54}; - 53 -> {52} [color=green style=dashed]; - 54 -> {55}; - 55 -> {56}; - 56 -> {57}; - 57 -> {58}; - 58 -> {59}; + + subgraph cluster_12 { + color=red + 59 [label="Enter function test1" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 60 [label="Enter block"]; + 61 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 62 [label="Const: String()"]; + 63 [label="Assignment: R|/x|"]; + 64 [label="Access variable R|/x|"]; + 65 [label="Smart cast: R|/x|"]; + 66 [label="Access variable R|kotlin/String.length|"]; + 67 [label="Postponed enter to lambda"]; + subgraph cluster_14 { + color=blue + 78 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_15 { + color=blue + 79 [label="Enter block"]; + 80 [label="Const: Int(1)"]; + 81 [label="Assignment: R|/x|"]; + 82 [label="Exit block"]; + } + 83 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 68 [label="Postponed exit from lambda"]; + 69 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 70 [label="Access variable R|/x|"]; + 71 [label="Smart cast: R|/x|"]; + 72 [label="Access variable #"]; + 73 [label="Access variable R|/x|"]; + 74 [label="Smart cast: R|/x|"]; + 75 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 76 [label="Exit block"]; + } + 77 [label="Exit function test1" style="filled" fillcolor=red]; + } + 59 -> {60}; 60 -> {61}; 61 -> {62}; 62 -> {63}; 63 -> {64}; 64 -> {65}; - 65 -> {53}; - - subgraph cluster_16 { - color=red - 66 [label="Enter function test2" style="filled" fillcolor=red]; - subgraph cluster_17 { - color=blue - 67 [label="Enter block"]; - 68 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 69 [label="Const: String()"]; - 70 [label="Assignment: R|/x|"]; - 71 [label="Access variable R|/x|"]; - 72 [label="Smart cast: R|/x|"]; - 73 [label="Access variable R|kotlin/String.length|"]; - 74 [label="Postponed enter to lambda"]; - subgraph cluster_18 { - color=blue - 85 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 86 [label="Enter block"]; - 87 [label="Const: Int(1)"]; - 88 [label="Assignment: R|/x|"]; - 89 [label="Exit block"]; - } - 90 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 75 [label="Postponed exit from lambda"]; - 76 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; - 77 [label="Access variable R|/x|"]; - 78 [label="Smart cast: R|/x|"]; - 79 [label="Access variable #"]; - 80 [label="Access variable R|/x|"]; - 81 [label="Smart cast: R|/x|"]; - 82 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 83 [label="Exit block"]; - } - 84 [label="Exit function test2" style="filled" fillcolor=red]; - } + 65 -> {66}; 66 -> {67}; - 67 -> {68}; + 67 -> {68 78 69}; + 67 -> {78} [style=dashed]; 68 -> {69}; + 68 -> {67} [color=green style=dashed]; 69 -> {70}; 70 -> {71}; 71 -> {72}; 72 -> {73}; 73 -> {74}; - 74 -> {85 76}; - 74 -> {75} [style=dotted]; - 74 -> {85} [style=dashed]; + 74 -> {75}; 75 -> {76}; - 75 -> {74} [color=green style=dashed]; 76 -> {77}; - 77 -> {78}; 78 -> {79}; 79 -> {80}; 80 -> {81}; 81 -> {82}; 82 -> {83}; - 83 -> {84}; + 83 -> {68}; + + subgraph cluster_16 { + color=red + 84 [label="Enter function test1m" style="filled" fillcolor=red]; + subgraph cluster_17 { + color=blue + 85 [label="Enter block"]; + 86 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 87 [label="Const: String()"]; + 88 [label="Assignment: R|/x|"]; + 89 [label="Access variable R|/x|"]; + 90 [label="Smart cast: R|/x|"]; + 91 [label="Access variable R|kotlin/String.length|"]; + 92 [label="Postponed enter to lambda"]; + subgraph cluster_18 { + color=blue + 100 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_19 { + color=blue + 101 [label="Enter block"]; + 102 [label="Const: String()"]; + 103 [label="Assignment: R|/x|"]; + 104 [label="Exit block"]; + } + 105 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 93 [label="Postponed exit from lambda"]; + 94 [label="Function call: R|/unknown|(...)" style="filled" fillcolor=yellow]; + 95 [label="Access variable R|/x|"]; + 96 [label="Smart cast: R|/x|"]; + 97 [label="Access variable R|kotlin/String.length|"]; + 98 [label="Exit block"]; + } + 99 [label="Exit function test1m" style="filled" fillcolor=red]; + } + 84 -> {85}; 85 -> {86}; 86 -> {87}; 87 -> {88}; 88 -> {89}; 89 -> {90}; - 90 -> {75}; - - subgraph cluster_20 { - color=red - 91 [label="Enter function test3" style="filled" fillcolor=red]; - subgraph cluster_21 { - color=blue - 92 [label="Enter block"]; - 93 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 94 [label="Const: String()"]; - 95 [label="Assignment: R|/x|"]; - 96 [label="Access variable R|/x|"]; - 97 [label="Smart cast: R|/x|"]; - 98 [label="Access variable R|kotlin/String.length|"]; - 99 [label="Postponed enter to lambda"]; - subgraph cluster_22 { - color=blue - 110 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_23 { - color=blue - 111 [label="Enter block"]; - 112 [label="Const: Int(1)"]; - 113 [label="Assignment: R|/x|"]; - 114 [label="Exit block"]; - } - 115 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 100 [label="Postponed exit from lambda"]; - 101 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; - 102 [label="Access variable R|/x|"]; - 103 [label="Smart cast: R|/x|"]; - 104 [label="Access variable #"]; - 105 [label="Access variable R|/x|"]; - 106 [label="Smart cast: R|/x|"]; - 107 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 108 [label="Exit block"]; - } - 109 [label="Exit function test3" style="filled" fillcolor=red]; - } + 90 -> {91}; 91 -> {92}; - 92 -> {93}; + 92 -> {93 100 94}; + 92 -> {100} [style=dashed]; 93 -> {94}; + 93 -> {92} [color=green style=dashed]; 94 -> {95}; 95 -> {96}; 96 -> {97}; 97 -> {98}; 98 -> {99}; - 99 -> {110 101}; - 99 -> {100} [style=dotted]; - 99 -> {110} [style=dashed]; 100 -> {101}; 101 -> {102}; 102 -> {103}; 103 -> {104}; 104 -> {105}; - 105 -> {106}; + 105 -> {93}; + + subgraph cluster_20 { + color=red + 106 [label="Enter function test2" style="filled" fillcolor=red]; + subgraph cluster_21 { + color=blue + 107 [label="Enter block"]; + 108 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 109 [label="Const: String()"]; + 110 [label="Assignment: R|/x|"]; + 111 [label="Access variable R|/x|"]; + 112 [label="Smart cast: R|/x|"]; + 113 [label="Access variable R|kotlin/String.length|"]; + 114 [label="Postponed enter to lambda"]; + subgraph cluster_22 { + color=blue + 125 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_23 { + color=blue + 126 [label="Enter block"]; + 127 [label="Const: Int(1)"]; + 128 [label="Assignment: R|/x|"]; + 129 [label="Exit block"]; + } + 130 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 115 [label="Postponed exit from lambda"]; + 116 [label="Function call: R|/atLeastOnce|(...)" style="filled" fillcolor=yellow]; + 117 [label="Access variable R|/x|"]; + 118 [label="Smart cast: R|/x|"]; + 119 [label="Access variable #"]; + 120 [label="Access variable R|/x|"]; + 121 [label="Smart cast: R|/x|"]; + 122 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 123 [label="Exit block"]; + } + 124 [label="Exit function test2" style="filled" fillcolor=red]; + } 106 -> {107}; 107 -> {108}; 108 -> {109}; + 109 -> {110}; 110 -> {111}; 111 -> {112}; 112 -> {113}; 113 -> {114}; - 114 -> {115}; - 115 -> {100}; - - subgraph cluster_24 { - color=red - 116 [label="Enter function test4" style="filled" fillcolor=red]; - subgraph cluster_25 { - color=blue - 117 [label="Enter block"]; - 118 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; - 119 [label="Const: String()"]; - 120 [label="Assignment: R|/x|"]; - 121 [label="Access variable R|/x|"]; - 122 [label="Smart cast: R|/x|"]; - 123 [label="Access variable R|kotlin/String.length|"]; - 124 [label="Postponed enter to lambda"]; - subgraph cluster_26 { - color=blue - 135 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_27 { - color=blue - 136 [label="Enter block"]; - 137 [label="Const: Int(1)"]; - 138 [label="Assignment: R|/x|"]; - 139 [label="Exit block"]; - } - 140 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 125 [label="Postponed exit from lambda"]; - 126 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; - 127 [label="Access variable R|/x|"]; - 128 [label="Smart cast: R|/x|"]; - 129 [label="Access variable #"]; - 130 [label="Access variable R|/x|"]; - 131 [label="Smart cast: R|/x|"]; - 132 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; - 133 [label="Exit block"]; - } - 134 [label="Exit function test4" style="filled" fillcolor=red]; - } + 114 -> {125 116}; + 114 -> {115} [style=dotted]; + 114 -> {125} [style=dashed]; + 115 -> {116}; + 115 -> {114} [color=green style=dashed]; 116 -> {117}; 117 -> {118}; 118 -> {119}; @@ -361,22 +273,138 @@ digraph flowFromInplaceLambda3_kt { 121 -> {122}; 122 -> {123}; 123 -> {124}; - 124 -> {125 135 126}; - 124 -> {135} [style=dashed]; 125 -> {126}; 126 -> {127}; 127 -> {128}; 128 -> {129}; 129 -> {130}; - 130 -> {131}; + 130 -> {115}; + + subgraph cluster_24 { + color=red + 131 [label="Enter function test3" style="filled" fillcolor=red]; + subgraph cluster_25 { + color=blue + 132 [label="Enter block"]; + 133 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 134 [label="Const: String()"]; + 135 [label="Assignment: R|/x|"]; + 136 [label="Access variable R|/x|"]; + 137 [label="Smart cast: R|/x|"]; + 138 [label="Access variable R|kotlin/String.length|"]; + 139 [label="Postponed enter to lambda"]; + subgraph cluster_26 { + color=blue + 150 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_27 { + color=blue + 151 [label="Enter block"]; + 152 [label="Const: Int(1)"]; + 153 [label="Assignment: R|/x|"]; + 154 [label="Exit block"]; + } + 155 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 140 [label="Postponed exit from lambda"]; + 141 [label="Function call: R|/exactlyOnce|(...)" style="filled" fillcolor=yellow]; + 142 [label="Access variable R|/x|"]; + 143 [label="Smart cast: R|/x|"]; + 144 [label="Access variable #"]; + 145 [label="Access variable R|/x|"]; + 146 [label="Smart cast: R|/x|"]; + 147 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 148 [label="Exit block"]; + } + 149 [label="Exit function test3" style="filled" fillcolor=red]; + } 131 -> {132}; 132 -> {133}; 133 -> {134}; + 134 -> {135}; 135 -> {136}; 136 -> {137}; 137 -> {138}; 138 -> {139}; - 139 -> {140}; - 140 -> {125}; + 139 -> {150 141}; + 139 -> {140} [style=dotted]; + 139 -> {150} [style=dashed]; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {144}; + 144 -> {145}; + 145 -> {146}; + 146 -> {147}; + 147 -> {148}; + 148 -> {149}; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; + 153 -> {154}; + 154 -> {155}; + 155 -> {140}; + + subgraph cluster_28 { + color=red + 156 [label="Enter function test4" style="filled" fillcolor=red]; + subgraph cluster_29 { + color=blue + 157 [label="Enter block"]; + 158 [label="Variable declaration: lvar x: R|kotlin/Any?|"]; + 159 [label="Const: String()"]; + 160 [label="Assignment: R|/x|"]; + 161 [label="Access variable R|/x|"]; + 162 [label="Smart cast: R|/x|"]; + 163 [label="Access variable R|kotlin/String.length|"]; + 164 [label="Postponed enter to lambda"]; + subgraph cluster_30 { + color=blue + 175 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_31 { + color=blue + 176 [label="Enter block"]; + 177 [label="Const: Int(1)"]; + 178 [label="Assignment: R|/x|"]; + 179 [label="Exit block"]; + } + 180 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 165 [label="Postponed exit from lambda"]; + 166 [label="Function call: R|/atMostOnce|(...)" style="filled" fillcolor=yellow]; + 167 [label="Access variable R|/x|"]; + 168 [label="Smart cast: R|/x|"]; + 169 [label="Access variable #"]; + 170 [label="Access variable R|/x|"]; + 171 [label="Smart cast: R|/x|"]; + 172 [label="Function call: R|/x|.#()" style="filled" fillcolor=yellow]; + 173 [label="Exit block"]; + } + 174 [label="Exit function test4" style="filled" fillcolor=red]; + } + 156 -> {157}; + 157 -> {158}; + 158 -> {159}; + 159 -> {160}; + 160 -> {161}; + 161 -> {162}; + 162 -> {163}; + 163 -> {164}; + 164 -> {165 175 166}; + 164 -> {175} [style=dashed]; + 165 -> {166}; + 166 -> {167}; + 167 -> {168}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {173}; + 173 -> {174}; + 175 -> {176}; + 176 -> {177}; + 177 -> {178}; + 178 -> {179}; + 179 -> {180}; + 180 -> {165}; } 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 e1ef87b1a0a..5ec4f3acff6 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.fir.txt @@ -5,7 +5,13 @@ FILE: flowFromInplaceLambda3.kt CallsInPlace(x, UNKNOWN) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.UNKNOWN|) + } + ) + } + R|/x|.R|SubstitutionOverride|() } public final fun atLeastOnce(x: R|() -> kotlin/Unit|): R|kotlin/Unit| @@ -14,7 +20,13 @@ FILE: flowFromInplaceLambda3.kt CallsInPlace(x, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() } public final fun exactlyOnce(x: R|() -> kotlin/Unit|): R|kotlin/Unit| @@ -23,7 +35,13 @@ FILE: flowFromInplaceLambda3.kt CallsInPlace(x, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() } public final fun atMostOnce(x: R|() -> kotlin/Unit|): R|kotlin/Unit| @@ -32,7 +50,13 @@ FILE: flowFromInplaceLambda3.kt CallsInPlace(x, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + } public final fun test1(): R|kotlin/Unit| { lvar x: R|kotlin/Any?| diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt index 1c30965ce0c..07010b46c6d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda3.kt @@ -1,4 +1,5 @@ // !DUMP_CFG +// !OPT_IN: kotlin.contracts.ExperimentalContracts import kotlin.contracts.* diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot index 05beb351a20..16bab7f93e3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.dot @@ -30,102 +30,93 @@ digraph flowFromTwoInplaceLambdas_kt { subgraph cluster_3 { color=blue 8 [label="Enter block"]; - 9 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 10 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 11 [label="Exit block"]; + subgraph cluster_4 { + color=blue + 9 [label="Enter block"]; + 10 [label="Exit block"]; + } + 11 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 12 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 13 [label="Exit block"]; } - 12 [label="Exit function run2" style="filled" fillcolor=red]; + 14 [label="Exit function run2" style="filled" fillcolor=red]; } 7 -> {8}; 8 -> {9}; 9 -> {10}; 10 -> {11}; 11 -> {12}; + 12 -> {13}; + 13 -> {14}; - subgraph cluster_4 { + subgraph cluster_5 { color=red - 13 [label="Enter function test1" style="filled" fillcolor=red]; - subgraph cluster_5 { + 27 [label="Enter function test1" style="filled" fillcolor=red]; + subgraph cluster_6 { color=blue - 14 [label="Enter block"]; - 15 [label="Access variable R|/x|"]; - 16 [label="Variable declaration: lvar p: R|kotlin/String?|"]; - subgraph cluster_6 { + 28 [label="Enter block"]; + 29 [label="Access variable R|/x|"]; + 30 [label="Variable declaration: lvar p: R|kotlin/String?|"]; + subgraph cluster_7 { color=blue - 17 [label="Enter when"]; - subgraph cluster_7 { - color=blue - 18 [label="Enter when branch condition "]; - 19 [label="Access variable R|/p|"]; - 20 [label="Const: Null(null)"]; - 21 [label="Equality operator !="]; - 22 [label="Exit when branch condition"]; - } - 23 [label="Synthetic else branch"]; - 24 [label="Enter when branch result"]; + 31 [label="Enter when"]; subgraph cluster_8 { color=blue - 25 [label="Enter block"]; - 26 [label="Postponed enter to lambda"]; - subgraph cluster_9 { - color=blue - 45 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_10 { - color=blue - 46 [label="Enter block"]; - 47 [label="Access variable R|/p|"]; - 48 [label="Smart cast: R|/p|"]; - 49 [label="Access variable R|kotlin/String.length#|"]; - 50 [label="Const: Int(123)"]; - 51 [label="Exit block"]; - } - 52 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_11 { - color=blue - 38 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_12 { - color=blue - 39 [label="Enter block"]; - 40 [label="Const: Null(null)"]; - 41 [label="Assignment: R|/p|"]; - 42 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 43 [label="Exit block"]; - } - 44 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 27 [label="Postponed exit from lambda"]; - 28 [label="Postponed exit from lambda"]; - 29 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 30 [label="Access variable R|/p|"]; - 31 [label="Smart cast: R|/p|"]; - 32 [label="Access variable R|kotlin/String.length#|"]; - 33 [label="Exit block"]; + 32 [label="Enter when branch condition "]; + 33 [label="Access variable R|/p|"]; + 34 [label="Const: Null(null)"]; + 35 [label="Equality operator !="]; + 36 [label="Exit when branch condition"]; } - 34 [label="Exit when branch result"]; - 35 [label="Exit when"]; + 37 [label="Synthetic else branch"]; + 38 [label="Enter when branch result"]; + subgraph cluster_9 { + color=blue + 39 [label="Enter block"]; + 40 [label="Postponed enter to lambda"]; + subgraph cluster_10 { + color=blue + 59 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_11 { + color=blue + 60 [label="Enter block"]; + 61 [label="Access variable R|/p|"]; + 62 [label="Smart cast: R|/p|"]; + 63 [label="Access variable R|kotlin/String.length#|"]; + 64 [label="Const: Int(123)"]; + 65 [label="Exit block"]; + } + 66 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_12 { + color=blue + 52 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 53 [label="Enter block"]; + 54 [label="Const: Null(null)"]; + 55 [label="Assignment: R|/p|"]; + 56 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 57 [label="Exit block"]; + } + 58 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 41 [label="Postponed exit from lambda"]; + 42 [label="Postponed exit from lambda"]; + 43 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 44 [label="Access variable R|/p|"]; + 45 [label="Smart cast: R|/p|"]; + 46 [label="Access variable R|kotlin/String.length#|"]; + 47 [label="Exit block"]; + } + 48 [label="Exit when branch result"]; + 49 [label="Exit when"]; } - 36 [label="Exit block"]; + 50 [label="Exit block"]; } - 37 [label="Exit function test1" style="filled" fillcolor=red]; + 51 [label="Exit function test1" style="filled" fillcolor=red]; } - 13 -> {14}; - 14 -> {15}; - 15 -> {16}; - 16 -> {17}; - 17 -> {18}; - 18 -> {19}; - 19 -> {20}; - 20 -> {21}; - 21 -> {22}; - 22 -> {24 23}; - 23 -> {35}; - 24 -> {25}; - 25 -> {26}; - 26 -> {38 45 29}; - 26 -> {28 27} [style=dotted]; - 26 -> {38 45} [style=dashed]; - 27 -> {29}; + 27 -> {28}; 28 -> {29}; 29 -> {30}; 30 -> {31}; @@ -134,107 +125,107 @@ digraph flowFromTwoInplaceLambdas_kt { 33 -> {34}; 34 -> {35}; 35 -> {36}; - 36 -> {37}; + 36 -> {38 37}; + 37 -> {49}; 38 -> {39}; 39 -> {40}; - 40 -> {41}; - 41 -> {42}; + 40 -> {52 59 43}; + 40 -> {42 41} [style=dotted]; + 40 -> {52 59} [style=dashed]; + 41 -> {43}; 42 -> {43}; 43 -> {44}; - 44 -> {28}; + 44 -> {45}; 45 -> {46}; 46 -> {47}; 47 -> {48}; 48 -> {49}; 49 -> {50}; 50 -> {51}; - 51 -> {52}; - 52 -> {27}; - - subgraph cluster_13 { - color=red - 53 [label="Enter function test1_tail" style="filled" fillcolor=red]; - subgraph cluster_14 { - color=blue - 54 [label="Enter block"]; - 55 [label="Access variable R|/x|"]; - 56 [label="Variable declaration: lvar p: R|kotlin/String?|"]; - subgraph cluster_15 { - color=blue - 57 [label="Enter when"]; - subgraph cluster_16 { - color=blue - 58 [label="Enter when branch condition "]; - 59 [label="Access variable R|/p|"]; - 60 [label="Const: Null(null)"]; - 61 [label="Equality operator !="]; - 62 [label="Exit when branch condition"]; - } - 63 [label="Synthetic else branch"]; - 64 [label="Enter when branch result"]; - subgraph cluster_17 { - color=blue - 65 [label="Enter block"]; - 66 [label="Postponed enter to lambda"]; - subgraph cluster_18 { - color=blue - 85 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 86 [label="Enter block"]; - 87 [label="Access variable R|/p|"]; - 88 [label="Smart cast: R|/p|"]; - 89 [label="Access variable R|kotlin/String.length#|"]; - 90 [label="Const: Int(123)"]; - 91 [label="Exit block"]; - } - 92 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_20 { - color=blue - 78 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_21 { - color=blue - 79 [label="Enter block"]; - 80 [label="Const: Null(null)"]; - 81 [label="Assignment: R|/p|"]; - 82 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 83 [label="Exit block"]; - } - 84 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 67 [label="Postponed exit from lambda"]; - 68 [label="Postponed exit from lambda"]; - 69 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 70 [label="Access variable R|/p|"]; - 71 [label="Smart cast: R|/p|"]; - 72 [label="Access variable R|kotlin/String.length#|"]; - 73 [label="Exit block"]; - } - 74 [label="Exit when branch result"]; - 75 [label="Exit when"]; - } - 76 [label="Exit block"]; - } - 77 [label="Exit function test1_tail" style="filled" fillcolor=red]; - } + 52 -> {53}; 53 -> {54}; 54 -> {55}; 55 -> {56}; 56 -> {57}; 57 -> {58}; - 58 -> {59}; + 58 -> {42}; 59 -> {60}; 60 -> {61}; 61 -> {62}; - 62 -> {64 63}; - 63 -> {75}; + 62 -> {63}; + 63 -> {64}; 64 -> {65}; 65 -> {66}; - 66 -> {78 85 69}; - 66 -> {68 67} [style=dotted]; - 66 -> {78 85} [style=dashed]; - 67 -> {69}; + 66 -> {41}; + + subgraph cluster_14 { + color=red + 67 [label="Enter function test1_tail" style="filled" fillcolor=red]; + subgraph cluster_15 { + color=blue + 68 [label="Enter block"]; + 69 [label="Access variable R|/x|"]; + 70 [label="Variable declaration: lvar p: R|kotlin/String?|"]; + subgraph cluster_16 { + color=blue + 71 [label="Enter when"]; + subgraph cluster_17 { + color=blue + 72 [label="Enter when branch condition "]; + 73 [label="Access variable R|/p|"]; + 74 [label="Const: Null(null)"]; + 75 [label="Equality operator !="]; + 76 [label="Exit when branch condition"]; + } + 77 [label="Synthetic else branch"]; + 78 [label="Enter when branch result"]; + subgraph cluster_18 { + color=blue + 79 [label="Enter block"]; + 80 [label="Postponed enter to lambda"]; + subgraph cluster_19 { + color=blue + 99 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_20 { + color=blue + 100 [label="Enter block"]; + 101 [label="Access variable R|/p|"]; + 102 [label="Smart cast: R|/p|"]; + 103 [label="Access variable R|kotlin/String.length#|"]; + 104 [label="Const: Int(123)"]; + 105 [label="Exit block"]; + } + 106 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_21 { + color=blue + 92 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_22 { + color=blue + 93 [label="Enter block"]; + 94 [label="Const: Null(null)"]; + 95 [label="Assignment: R|/p|"]; + 96 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 97 [label="Exit block"]; + } + 98 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 81 [label="Postponed exit from lambda"]; + 82 [label="Postponed exit from lambda"]; + 83 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 84 [label="Access variable R|/p|"]; + 85 [label="Smart cast: R|/p|"]; + 86 [label="Access variable R|kotlin/String.length#|"]; + 87 [label="Exit block"]; + } + 88 [label="Exit when branch result"]; + 89 [label="Exit when"]; + } + 90 [label="Exit block"]; + } + 91 [label="Exit function test1_tail" style="filled" fillcolor=red]; + } + 67 -> {68}; 68 -> {69}; 69 -> {70}; 70 -> {71}; @@ -243,569 +234,585 @@ digraph flowFromTwoInplaceLambdas_kt { 73 -> {74}; 74 -> {75}; 75 -> {76}; - 76 -> {77}; + 76 -> {78 77}; + 77 -> {89}; 78 -> {79}; 79 -> {80}; - 80 -> {81}; - 81 -> {82}; + 80 -> {92 99 83}; + 80 -> {82 81} [style=dotted]; + 80 -> {92 99} [style=dashed]; + 81 -> {83}; 82 -> {83}; 83 -> {84}; - 84 -> {68}; + 84 -> {85}; 85 -> {86}; 86 -> {87}; 87 -> {88}; 88 -> {89}; 89 -> {90}; 90 -> {91}; - 91 -> {92}; - 92 -> {67}; - - subgraph cluster_22 { - color=red - 93 [label="Enter function test2" style="filled" fillcolor=red]; - subgraph cluster_23 { - color=blue - 94 [label="Enter block"]; - 95 [label="Access variable R|/x|"]; - 96 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; - 97 [label="Access variable R|/p|"]; - 98 [label="Access variable #"]; - 99 [label="Postponed enter to lambda"]; - subgraph cluster_24 { - color=blue - 120 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_25 { - color=blue - 121 [label="Enter block"]; - 122 [label="Access variable R|/p|"]; - 123 [label="Type operator: (R|/p| as R|kotlin/String|)"]; - 124 [label="Const: Int(123)"]; - 125 [label="Exit block"]; - } - 126 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_26 { - color=blue - 113 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_27 { - color=blue - 114 [label="Enter block"]; - 115 [label="Const: Null(null)"]; - 116 [label="Assignment: R|/p|"]; - 117 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 118 [label="Exit block"]; - } - 119 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 100 [label="Postponed exit from lambda"]; - 101 [label="Postponed exit from lambda"]; - 102 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 103 [label="Access variable R|/p|"]; - 104 [label="Smart cast: R|/p|"]; - 105 [label="Access variable #"]; - 106 [label="Access variable R|/p|"]; - 107 [label="Smart cast: R|/p|"]; - 108 [label="Enter safe call"]; - 109 [label="Access variable #"]; - 110 [label="Exit safe call"]; - 111 [label="Exit block"]; - } - 112 [label="Exit function test2" style="filled" fillcolor=red]; - } + 92 -> {93}; 93 -> {94}; 94 -> {95}; 95 -> {96}; 96 -> {97}; 97 -> {98}; - 98 -> {99}; - 99 -> {113 120 102}; - 99 -> {101 100} [style=dotted]; - 99 -> {113 120} [style=dashed]; - 100 -> {102}; + 98 -> {82}; + 99 -> {100}; + 100 -> {101}; 101 -> {102}; 102 -> {103}; 103 -> {104}; 104 -> {105}; 105 -> {106}; - 106 -> {107}; - 107 -> {108 110}; + 106 -> {81}; + + subgraph cluster_23 { + color=red + 107 [label="Enter function test2" style="filled" fillcolor=red]; + subgraph cluster_24 { + color=blue + 108 [label="Enter block"]; + 109 [label="Access variable R|/x|"]; + 110 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 111 [label="Access variable R|/p|"]; + 112 [label="Access variable #"]; + 113 [label="Postponed enter to lambda"]; + subgraph cluster_25 { + color=blue + 134 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_26 { + color=blue + 135 [label="Enter block"]; + 136 [label="Access variable R|/p|"]; + 137 [label="Type operator: (R|/p| as R|kotlin/String|)"]; + 138 [label="Const: Int(123)"]; + 139 [label="Exit block"]; + } + 140 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_27 { + color=blue + 127 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_28 { + color=blue + 128 [label="Enter block"]; + 129 [label="Const: Null(null)"]; + 130 [label="Assignment: R|/p|"]; + 131 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 132 [label="Exit block"]; + } + 133 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 114 [label="Postponed exit from lambda"]; + 115 [label="Postponed exit from lambda"]; + 116 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 117 [label="Access variable R|/p|"]; + 118 [label="Smart cast: R|/p|"]; + 119 [label="Access variable #"]; + 120 [label="Access variable R|/p|"]; + 121 [label="Smart cast: R|/p|"]; + 122 [label="Enter safe call"]; + 123 [label="Access variable #"]; + 124 [label="Exit safe call"]; + 125 [label="Exit block"]; + } + 126 [label="Exit function test2" style="filled" fillcolor=red]; + } + 107 -> {108}; 108 -> {109}; 109 -> {110}; 110 -> {111}; 111 -> {112}; - 113 -> {114}; - 114 -> {115}; + 112 -> {113}; + 113 -> {127 134 116}; + 113 -> {115 114} [style=dotted]; + 113 -> {127 134} [style=dashed]; + 114 -> {116}; 115 -> {116}; 116 -> {117}; 117 -> {118}; 118 -> {119}; - 119 -> {101}; + 119 -> {120}; 120 -> {121}; - 121 -> {122}; + 121 -> {122 124}; 122 -> {123}; 123 -> {124}; 124 -> {125}; 125 -> {126}; - 126 -> {100}; - - subgraph cluster_28 { - color=red - 127 [label="Enter function test3" style="filled" fillcolor=red]; - subgraph cluster_29 { - color=blue - 128 [label="Enter block"]; - 129 [label="Access variable R|/x|"]; - 130 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; - 131 [label="Access variable R|/p|"]; - 132 [label="Access variable #"]; - 133 [label="Postponed enter to lambda"]; - subgraph cluster_30 { - color=blue - 154 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_31 { - color=blue - 155 [label="Enter block"]; - 156 [label="Const: String()"]; - 157 [label="Assignment: R|/p|"]; - 158 [label="Const: Int(123)"]; - 159 [label="Exit block"]; - } - 160 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_32 { - color=blue - 147 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_33 { - color=blue - 148 [label="Enter block"]; - 149 [label="Const: Null(null)"]; - 150 [label="Assignment: R|/p|"]; - 151 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 152 [label="Exit block"]; - } - 153 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 134 [label="Postponed exit from lambda"]; - 135 [label="Postponed exit from lambda"]; - 136 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 137 [label="Access variable R|/p|"]; - 138 [label="Smart cast: R|/p|"]; - 139 [label="Access variable R|kotlin/String.length#|"]; - 140 [label="Access variable R|/p|"]; - 141 [label="Smart cast: R|/p|"]; - 142 [label="Enter safe call"]; - 143 [label="Access variable R|kotlin/String.length|"]; - 144 [label="Exit safe call"]; - 145 [label="Exit block"]; - } - 146 [label="Exit function test3" style="filled" fillcolor=red]; - } 127 -> {128}; 128 -> {129}; 129 -> {130}; 130 -> {131}; 131 -> {132}; 132 -> {133}; - 133 -> {147 154 136}; - 133 -> {135 134} [style=dotted]; - 133 -> {147 154} [style=dashed]; - 134 -> {136}; + 133 -> {115}; + 134 -> {135}; 135 -> {136}; 136 -> {137}; 137 -> {138}; 138 -> {139}; 139 -> {140}; - 140 -> {141}; - 141 -> {142 144}; + 140 -> {114}; + + subgraph cluster_29 { + color=red + 141 [label="Enter function test3" style="filled" fillcolor=red]; + subgraph cluster_30 { + color=blue + 142 [label="Enter block"]; + 143 [label="Access variable R|/x|"]; + 144 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 145 [label="Access variable R|/p|"]; + 146 [label="Access variable #"]; + 147 [label="Postponed enter to lambda"]; + subgraph cluster_31 { + color=blue + 168 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_32 { + color=blue + 169 [label="Enter block"]; + 170 [label="Const: String()"]; + 171 [label="Assignment: R|/p|"]; + 172 [label="Const: Int(123)"]; + 173 [label="Exit block"]; + } + 174 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_33 { + color=blue + 161 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_34 { + color=blue + 162 [label="Enter block"]; + 163 [label="Const: Null(null)"]; + 164 [label="Assignment: R|/p|"]; + 165 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 166 [label="Exit block"]; + } + 167 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 148 [label="Postponed exit from lambda"]; + 149 [label="Postponed exit from lambda"]; + 150 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 151 [label="Access variable R|/p|"]; + 152 [label="Smart cast: R|/p|"]; + 153 [label="Access variable R|kotlin/String.length#|"]; + 154 [label="Access variable R|/p|"]; + 155 [label="Smart cast: R|/p|"]; + 156 [label="Enter safe call"]; + 157 [label="Access variable R|kotlin/String.length|"]; + 158 [label="Exit safe call"]; + 159 [label="Exit block"]; + } + 160 [label="Exit function test3" style="filled" fillcolor=red]; + } + 141 -> {142}; 142 -> {143}; 143 -> {144}; 144 -> {145}; 145 -> {146}; - 147 -> {148}; - 148 -> {149}; + 146 -> {147}; + 147 -> {161 168 150}; + 147 -> {149 148} [style=dotted]; + 147 -> {161 168} [style=dashed]; + 148 -> {150}; 149 -> {150}; 150 -> {151}; 151 -> {152}; 152 -> {153}; - 153 -> {135}; + 153 -> {154}; 154 -> {155}; - 155 -> {156}; + 155 -> {156 158}; 156 -> {157}; 157 -> {158}; 158 -> {159}; 159 -> {160}; - 160 -> {134}; - - subgraph cluster_34 { - color=red - 161 [label="Enter class I1" style="filled" fillcolor=red]; - 162 [label="Exit class I1" style="filled" fillcolor=red]; - } - 161 -> {162} [color=green]; - - subgraph cluster_35 { - color=red - 163 [label="Enter class I2" style="filled" fillcolor=red]; - 164 [label="Exit class I2" style="filled" fillcolor=red]; - } - 163 -> {164} [color=green]; - - subgraph cluster_36 { - color=red - 165 [label="Enter function test4" style="filled" fillcolor=red]; - subgraph cluster_37 { - color=blue - 166 [label="Enter block"]; - 167 [label="Access variable R|/x|"]; - 168 [label="Access variable #"]; - 169 [label="Access variable R|/x|"]; - 170 [label="Access variable #"]; - 171 [label="Postponed enter to lambda"]; - subgraph cluster_38 { - color=blue - 193 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_39 { - color=blue - 194 [label="Enter block"]; - 195 [label="Access variable R|/x|"]; - 196 [label="Type operator: (R|/x| as R|I2|)"]; - 197 [label="Access variable R|/x|"]; - 198 [label="Smart cast: R|/x|"]; - 199 [label="Access variable #"]; - 200 [label="Const: Int(123)"]; - 201 [label="Exit block"]; - } - 202 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_40 { - color=blue - 183 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_41 { - color=blue - 184 [label="Enter block"]; - 185 [label="Access variable R|/x|"]; - 186 [label="Type operator: (R|/x| as R|I1|)"]; - 187 [label="Access variable R|/x|"]; - 188 [label="Smart cast: R|/x|"]; - 189 [label="Access variable #"]; - 190 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 191 [label="Exit block"]; - } - 192 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 172 [label="Postponed exit from lambda"]; - 173 [label="Postponed exit from lambda"]; - 174 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 175 [label="Access variable R|/x|"]; - 176 [label="Smart cast: R|/x|"]; - 177 [label="Access variable R|/I1.x|"]; - 178 [label="Access variable R|/x|"]; - 179 [label="Smart cast: R|/x|"]; - 180 [label="Access variable R|/I2.y|"]; - 181 [label="Exit block"]; - } - 182 [label="Exit function test4" style="filled" fillcolor=red]; - } + 161 -> {162}; + 162 -> {163}; + 163 -> {164}; + 164 -> {165}; 165 -> {166}; 166 -> {167}; - 167 -> {168}; + 167 -> {149}; 168 -> {169}; 169 -> {170}; 170 -> {171}; - 171 -> {183 193 174}; - 171 -> {173 172} [style=dotted]; - 171 -> {183 193} [style=dashed]; - 172 -> {174}; + 171 -> {172}; + 172 -> {173}; 173 -> {174}; - 174 -> {175}; - 175 -> {176}; - 176 -> {177}; - 177 -> {178}; - 178 -> {179}; + 174 -> {148}; + + subgraph cluster_35 { + color=red + 175 [label="Enter class I1" style="filled" fillcolor=red]; + 176 [label="Exit class I1" style="filled" fillcolor=red]; + } + 175 -> {176} [color=green]; + + subgraph cluster_36 { + color=red + 177 [label="Enter class I2" style="filled" fillcolor=red]; + 178 [label="Exit class I2" style="filled" fillcolor=red]; + } + 177 -> {178} [color=green]; + + subgraph cluster_37 { + color=red + 179 [label="Enter function test4" style="filled" fillcolor=red]; + subgraph cluster_38 { + color=blue + 180 [label="Enter block"]; + 181 [label="Access variable R|/x|"]; + 182 [label="Access variable #"]; + 183 [label="Access variable R|/x|"]; + 184 [label="Access variable #"]; + 185 [label="Postponed enter to lambda"]; + subgraph cluster_39 { + color=blue + 207 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_40 { + color=blue + 208 [label="Enter block"]; + 209 [label="Access variable R|/x|"]; + 210 [label="Type operator: (R|/x| as R|I2|)"]; + 211 [label="Access variable R|/x|"]; + 212 [label="Smart cast: R|/x|"]; + 213 [label="Access variable #"]; + 214 [label="Const: Int(123)"]; + 215 [label="Exit block"]; + } + 216 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_41 { + color=blue + 197 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_42 { + color=blue + 198 [label="Enter block"]; + 199 [label="Access variable R|/x|"]; + 200 [label="Type operator: (R|/x| as R|I1|)"]; + 201 [label="Access variable R|/x|"]; + 202 [label="Smart cast: R|/x|"]; + 203 [label="Access variable #"]; + 204 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 205 [label="Exit block"]; + } + 206 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 186 [label="Postponed exit from lambda"]; + 187 [label="Postponed exit from lambda"]; + 188 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 189 [label="Access variable R|/x|"]; + 190 [label="Smart cast: R|/x|"]; + 191 [label="Access variable R|/I1.x|"]; + 192 [label="Access variable R|/x|"]; + 193 [label="Smart cast: R|/x|"]; + 194 [label="Access variable R|/I2.y|"]; + 195 [label="Exit block"]; + } + 196 [label="Exit function test4" style="filled" fillcolor=red]; + } 179 -> {180}; 180 -> {181}; 181 -> {182}; + 182 -> {183}; 183 -> {184}; 184 -> {185}; - 185 -> {186}; - 186 -> {187}; + 185 -> {197 207 188}; + 185 -> {187 186} [style=dotted]; + 185 -> {197 207} [style=dashed]; + 186 -> {188}; 187 -> {188}; 188 -> {189}; 189 -> {190}; 190 -> {191}; 191 -> {192}; - 192 -> {173}; + 192 -> {193}; 193 -> {194}; 194 -> {195}; 195 -> {196}; - 196 -> {197}; 197 -> {198}; 198 -> {199}; 199 -> {200}; 200 -> {201}; 201 -> {202}; - 202 -> {172}; - - subgraph cluster_42 { - color=red - 203 [label="Enter function test5" style="filled" fillcolor=red]; - subgraph cluster_43 { - color=blue - 204 [label="Enter block"]; - 205 [label="Access variable R|/x|"]; - 206 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; - 207 [label="Access variable R|/p|"]; - 208 [label="Access variable #"]; - 209 [label="Postponed enter to lambda"]; - subgraph cluster_44 { - color=blue - 230 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_45 { - color=blue - 231 [label="Enter block"]; - 232 [label="Access variable R|/q|"]; - 233 [label="Assignment: R|/p|"]; - 234 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; - 235 [label="Exit block"]; - } - 236 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_46 { - color=blue - 223 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_47 { - color=blue - 224 [label="Enter block"]; - 225 [label="Access variable R|/p|"]; - 226 [label="Type operator: (R|/p| as R|kotlin/Int|)"]; - 227 [label="Const: Int(123)"]; - 228 [label="Exit block"]; - } - 229 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 210 [label="Postponed exit from lambda"]; - 211 [label="Postponed exit from lambda"]; - 212 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 213 [label="Access variable R|/p|"]; - 214 [label="Smart cast: R|/p|"]; - 215 [label="Access variable R|kotlin/String.length#|"]; - 216 [label="Access variable R|/p|"]; - 217 [label="Smart cast: R|/p|"]; - 218 [label="Enter safe call"]; - 219 [label="Access variable R|kotlin/String.length|"]; - 220 [label="Exit safe call"]; - 221 [label="Exit block"]; - } - 222 [label="Exit function test5" style="filled" fillcolor=red]; - } + 202 -> {203}; 203 -> {204}; 204 -> {205}; 205 -> {206}; - 206 -> {207}; + 206 -> {187}; 207 -> {208}; 208 -> {209}; - 209 -> {223 230 212}; - 209 -> {211 210} [style=dotted]; - 209 -> {223 230} [style=dashed]; - 210 -> {212}; + 209 -> {210}; + 210 -> {211}; 211 -> {212}; 212 -> {213}; 213 -> {214}; 214 -> {215}; 215 -> {216}; - 216 -> {217}; - 217 -> {218 220}; + 216 -> {186}; + + subgraph cluster_43 { + color=red + 217 [label="Enter function test5" style="filled" fillcolor=red]; + subgraph cluster_44 { + color=blue + 218 [label="Enter block"]; + 219 [label="Access variable R|/x|"]; + 220 [label="Variable declaration: lvar p: R|kotlin/Any?|"]; + 221 [label="Access variable R|/p|"]; + 222 [label="Access variable #"]; + 223 [label="Postponed enter to lambda"]; + subgraph cluster_45 { + color=blue + 244 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_46 { + color=blue + 245 [label="Enter block"]; + 246 [label="Access variable R|/q|"]; + 247 [label="Assignment: R|/p|"]; + 248 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 249 [label="Exit block"]; + } + 250 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_47 { + color=blue + 237 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_48 { + color=blue + 238 [label="Enter block"]; + 239 [label="Access variable R|/p|"]; + 240 [label="Type operator: (R|/p| as R|kotlin/Int|)"]; + 241 [label="Const: Int(123)"]; + 242 [label="Exit block"]; + } + 243 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 224 [label="Postponed exit from lambda"]; + 225 [label="Postponed exit from lambda"]; + 226 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 227 [label="Access variable R|/p|"]; + 228 [label="Smart cast: R|/p|"]; + 229 [label="Access variable R|kotlin/String.length#|"]; + 230 [label="Access variable R|/p|"]; + 231 [label="Smart cast: R|/p|"]; + 232 [label="Enter safe call"]; + 233 [label="Access variable R|kotlin/String.length|"]; + 234 [label="Exit safe call"]; + 235 [label="Exit block"]; + } + 236 [label="Exit function test5" style="filled" fillcolor=red]; + } + 217 -> {218}; 218 -> {219}; 219 -> {220}; 220 -> {221}; 221 -> {222}; - 223 -> {224}; - 224 -> {225}; + 222 -> {223}; + 223 -> {237 244 226}; + 223 -> {225 224} [style=dotted]; + 223 -> {237 244} [style=dashed]; + 224 -> {226}; 225 -> {226}; 226 -> {227}; 227 -> {228}; 228 -> {229}; - 229 -> {211}; + 229 -> {230}; 230 -> {231}; - 231 -> {232}; + 231 -> {232 234}; 232 -> {233}; 233 -> {234}; 234 -> {235}; 235 -> {236}; - 236 -> {210}; - - subgraph cluster_48 { - color=red - 237 [label="Enter function test6" style="filled" fillcolor=red]; - subgraph cluster_49 { - color=blue - 238 [label="Enter block"]; - 239 [label="Variable declaration: lval x: R|kotlin/String|"]; - 240 [label="Postponed enter to lambda"]; - subgraph cluster_50 { - color=blue - 256 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_51 { - color=blue - 257 [label="Enter block"]; - 258 [label="Access variable R|/x|"]; - 259 [label="Access variable R|kotlin/String.length|"]; - 260 [label="Exit block"]; - } - 261 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_52 { - color=blue - 248 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_53 { - color=blue - 249 [label="Enter block"]; - 250 [label="Const: String()"]; - 251 [label="Assignment: R|/x|"]; - 252 [label="Access variable R|/x|"]; - 253 [label="Access variable R|kotlin/String.length|"]; - 254 [label="Exit block"]; - } - 255 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 241 [label="Postponed exit from lambda"]; - 242 [label="Postponed exit from lambda"]; - 243 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - 244 [label="Access variable R|/x|"]; - 245 [label="Access variable R|kotlin/String.length|"]; - 246 [label="Exit block"]; - } - 247 [label="Exit function test6" style="filled" fillcolor=red]; - } 237 -> {238}; 238 -> {239}; 239 -> {240}; - 240 -> {248 256 243}; - 240 -> {242 241} [style=dotted]; - 240 -> {248 256} [style=dashed]; - 241 -> {243}; + 240 -> {241}; + 241 -> {242}; 242 -> {243}; - 243 -> {244}; + 243 -> {225}; 244 -> {245}; 245 -> {246}; 246 -> {247}; + 247 -> {248}; 248 -> {249}; 249 -> {250}; - 250 -> {251}; + 250 -> {224}; + + subgraph cluster_49 { + color=red + 251 [label="Enter function test6" style="filled" fillcolor=red]; + subgraph cluster_50 { + color=blue + 252 [label="Enter block"]; + 253 [label="Variable declaration: lval x: R|kotlin/String|"]; + 254 [label="Postponed enter to lambda"]; + subgraph cluster_51 { + color=blue + 270 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_52 { + 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]; + } + subgraph cluster_53 { + color=blue + 262 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_54 { + 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]; + } + 255 [label="Postponed exit from lambda"]; + 256 [label="Postponed exit from lambda"]; + 257 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + 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]; + } 251 -> {252}; 252 -> {253}; 253 -> {254}; - 254 -> {255}; - 255 -> {242}; + 254 -> {262 270 257}; + 254 -> {256 255} [style=dotted]; + 254 -> {262 270} [style=dashed]; + 255 -> {257}; 256 -> {257}; 257 -> {258}; 258 -> {259}; 259 -> {260}; 260 -> {261}; - 261 -> {241}; - - subgraph cluster_54 { - color=red - 262 [label="Enter function test7" style="filled" fillcolor=red]; - subgraph cluster_55 { - color=blue - 263 [label="Enter block"]; - 264 [label="Const: String()"]; - 265 [label="Variable declaration: lval x: R|kotlin/Any?|"]; - 266 [label="Variable declaration: lval y: R|kotlin/Any?|"]; - 267 [label="Postponed enter to lambda"]; - subgraph cluster_56 { - color=blue - 293 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_57 { - color=blue - 294 [label="Enter block"]; - 295 [label="Jump: ^@run2 Unit"]; - 296 [label="Stub" style="filled" fillcolor=gray]; - 297 [label="Exit block" style="filled" fillcolor=gray]; - } - 298 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - subgraph cluster_58 { - color=blue - 287 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_59 { - color=blue - 288 [label="Enter block"]; - 289 [label="Access variable R|/x|"]; - 290 [label="Assignment: R|/y|"]; - 291 [label="Exit block"]; - } - 292 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 268 [label="Postponed exit from lambda"]; - 269 [label="Postponed exit from lambda"]; - 270 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; - subgraph cluster_60 { - color=blue - 271 [label="Enter when"]; - subgraph cluster_61 { - color=blue - 272 [label="Enter when branch condition "]; - 273 [label="Access variable R|/y|"]; - 274 [label="Type operator: (R|/y| is R|kotlin/String|)"]; - 275 [label="Exit when branch condition"]; - } - 276 [label="Synthetic else branch"]; - 277 [label="Enter when branch result"]; - subgraph cluster_62 { - color=blue - 278 [label="Enter block"]; - 279 [label="Access variable R|/x|"]; - 280 [label="Smart cast: R|/x|"]; - 281 [label="Access variable R|kotlin/String.length|"]; - 282 [label="Exit block"]; - } - 283 [label="Exit when branch result"]; - 284 [label="Exit when"]; - } - 285 [label="Exit block"]; - } - 286 [label="Exit function test7" style="filled" fillcolor=red]; - } 262 -> {263}; 263 -> {264}; 264 -> {265}; 265 -> {266}; 266 -> {267}; - 267 -> {287 293 270}; - 267 -> {269 268} [style=dotted]; - 267 -> {287 293} [style=dashed]; - 268 -> {270}; - 269 -> {270}; + 267 -> {268}; + 268 -> {269}; + 269 -> {256}; 270 -> {271}; 271 -> {272}; 272 -> {273}; 273 -> {274}; 274 -> {275}; - 275 -> {277 276}; - 276 -> {284}; + 275 -> {255}; + + subgraph cluster_55 { + color=red + 276 [label="Enter function test7" style="filled" fillcolor=red]; + subgraph cluster_56 { + 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_57 { + color=blue + 307 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_58 { + color=blue + 308 [label="Enter block"]; + 309 [label="Jump: ^@run2 Unit"]; + 310 [label="Stub" style="filled" fillcolor=gray]; + 311 [label="Exit block" style="filled" fillcolor=gray]; + } + 312 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + subgraph cluster_59 { + color=blue + 301 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_60 { + color=blue + 302 [label="Enter block"]; + 303 [label="Access variable R|/x|"]; + 304 [label="Assignment: R|/y|"]; + 305 [label="Exit block"]; + } + 306 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 282 [label="Postponed exit from lambda"]; + 283 [label="Postponed exit from lambda"]; + 284 [label="Function call: R|/run2|(...)" style="filled" fillcolor=yellow]; + subgraph cluster_61 { + color=blue + 285 [label="Enter when"]; + subgraph cluster_62 { + color=blue + 286 [label="Enter when branch condition "]; + 287 [label="Access variable R|/y|"]; + 288 [label="Type operator: (R|/y| is R|kotlin/String|)"]; + 289 [label="Exit when branch condition"]; + } + 290 [label="Synthetic else branch"]; + 291 [label="Enter when branch result"]; + subgraph cluster_63 { + color=blue + 292 [label="Enter block"]; + 293 [label="Access variable R|/x|"]; + 294 [label="Smart cast: R|/x|"]; + 295 [label="Access variable R|kotlin/String.length|"]; + 296 [label="Exit block"]; + } + 297 [label="Exit when branch result"]; + 298 [label="Exit when"]; + } + 299 [label="Exit block"]; + } + 300 [label="Exit function test7" style="filled" fillcolor=red]; + } + 276 -> {277}; 277 -> {278}; 278 -> {279}; 279 -> {280}; 280 -> {281}; - 281 -> {282}; - 282 -> {283}; + 281 -> {301 307 284}; + 281 -> {283 282} [style=dotted]; + 281 -> {301 307} [style=dashed]; + 282 -> {284}; 283 -> {284}; 284 -> {285}; 285 -> {286}; + 286 -> {287}; 287 -> {288}; 288 -> {289}; - 289 -> {290}; - 290 -> {291}; + 289 -> {291 290}; + 290 -> {298}; 291 -> {292}; - 292 -> {269}; + 292 -> {293}; 293 -> {294}; 294 -> {295}; - 295 -> {298}; - 295 -> {296} [style=dotted]; - 296 -> {297} [style=dotted]; - 297 -> {298} [style=dotted]; - 298 -> {268}; + 295 -> {296}; + 296 -> {297}; + 297 -> {298}; + 298 -> {299}; + 299 -> {300}; + 301 -> {302}; + 302 -> {303}; + 303 -> {304}; + 304 -> {305}; + 305 -> {306}; + 306 -> {283}; + 307 -> {308}; + 308 -> {309}; + 309 -> {312}; + 309 -> {310} [style=dotted]; + 310 -> {311} [style=dotted]; + 311 -> {312} [style=dotted]; + 312 -> {282}; } 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 bc662ef8277..2c291f3162d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.fir.txt @@ -2,14 +2,21 @@ FILE: flowFromTwoInplaceLambdas.kt public final fun n(): R|T?| { ^n Null(null) } - public final fun run2(x: R|() -> T|, y: R|() -> T|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun run2(x: R|() -> T|, y: R|() -> T|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, EXACTLY_ONCE) CallsInPlace(y, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/y|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() R|/y|.R|SubstitutionOverride|() } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt index 853f8ec015d..b97a592d0a3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromTwoInplaceLambdas.kt @@ -3,6 +3,7 @@ import kotlin.contracts.* fun n(): T? = null +@OptIn(ExperimentalContracts::class) fun run2(x: () -> T, y: () -> T) { contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.dot index 0a0fc13f387..5fa652dadcb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.dot @@ -25,15 +25,20 @@ digraph postponedLambdaInReturn_kt { subgraph cluster_3 { color=blue 6 [label="Enter block"]; - 7 [label="Function call: R|/Lateinit.Lateinit|()" style="filled" fillcolor=yellow]; - 8 [label="Access variable R|/builder|"]; - 9 [label="Function call: R|/Lateinit.Lateinit|().R|kotlin/apply||>(...)" style="filled" fillcolor=yellow]; - 10 [label="Access variable R|SubstitutionOverride|"]; - 11 [label="Jump: ^build R|/Lateinit.Lateinit|().R|kotlin/apply||>(R|/builder|).R|SubstitutionOverride|"]; - 12 [label="Stub" style="filled" fillcolor=gray]; - 13 [label="Exit block" style="filled" fillcolor=gray]; + subgraph cluster_4 { + color=blue + 7 [label="Enter block"]; + 8 [label="Exit block"]; + } + 9 [label="Function call: R|/Lateinit.Lateinit|()" style="filled" fillcolor=yellow]; + 10 [label="Access variable R|/builder|"]; + 11 [label="Function call: R|/Lateinit.Lateinit|().R|kotlin/apply||>(...)" style="filled" fillcolor=yellow]; + 12 [label="Access variable R|SubstitutionOverride|"]; + 13 [label="Jump: ^build R|/Lateinit.Lateinit|().R|kotlin/apply||>(R|/builder|).R|SubstitutionOverride|"]; + 14 [label="Stub" style="filled" fillcolor=gray]; + 15 [label="Exit block" style="filled" fillcolor=gray]; } - 14 [label="Exit function build" style="filled" fillcolor=red]; + 16 [label="Exit function build" style="filled" fillcolor=red]; } 5 -> {6}; 6 -> {7}; @@ -41,450 +46,452 @@ digraph postponedLambdaInReturn_kt { 8 -> {9}; 9 -> {10}; 10 -> {11}; - 11 -> {14}; - 11 -> {12} [style=dotted]; - 12 -> {13} [style=dotted]; + 11 -> {12}; + 12 -> {13}; + 13 -> {16}; 13 -> {14} [style=dotted]; - - subgraph cluster_4 { - color=red - 15 [label="Enter property" style="filled" fillcolor=red]; - 16 [label="Const: Boolean(false)"]; - 17 [label="Exit property" style="filled" fillcolor=red]; - } - 15 -> {16}; - 16 -> {17}; + 14 -> {15} [style=dotted]; + 15 -> {16} [style=dotted]; subgraph cluster_5 { color=red - 18 [label="Enter function test1" style="filled" fillcolor=red]; - subgraph cluster_6 { + 25 [label="Enter property" style="filled" fillcolor=red]; + 26 [label="Const: Boolean(false)"]; + 27 [label="Exit property" style="filled" fillcolor=red]; + } + 25 -> {26}; + 26 -> {27}; + + subgraph cluster_6 { + color=red + 28 [label="Enter function test1" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 19 [label="Enter block"]; - 20 [label="Const: Null(null)"]; - 21 [label="Variable declaration: lvar y: R|kotlin/String?|"]; - 22 [label="Postponed enter to lambda"]; - subgraph cluster_7 { + 29 [label="Enter block"]; + 30 [label="Const: Null(null)"]; + 31 [label="Variable declaration: lvar y: R|kotlin/String?|"]; + 32 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 30 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_8 { + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 31 [label="Enter block"]; - subgraph cluster_9 { + 41 [label="Enter block"]; + subgraph cluster_10 { color=blue - 32 [label="Enter when"]; - subgraph cluster_10 { - color=blue - 33 [label="Enter when branch condition "]; - 34 [label="Access variable R|/p|"]; - 35 [label="Exit when branch condition"]; - } + 42 [label="Enter when"]; subgraph cluster_11 { color=blue - 36 [label="Enter when branch condition else"]; - 37 [label="Exit when branch condition"]; + 43 [label="Enter when branch condition "]; + 44 [label="Access variable R|/p|"]; + 45 [label="Exit when branch condition"]; } - 38 [label="Enter when branch result"]; subgraph cluster_12 { color=blue - 39 [label="Enter block"]; - 40 [label="Const: String()"]; - 41 [label="Jump: ^@run String()"]; - 42 [label="Stub" style="filled" fillcolor=gray]; - 43 [label="Exit block" style="filled" fillcolor=gray]; + 46 [label="Enter when branch condition else"]; + 47 [label="Exit when branch condition"]; } - 44 [label="Exit when branch result" style="filled" fillcolor=gray]; - 45 [label="Enter when branch result"]; + 48 [label="Enter when branch result"]; subgraph cluster_13 { color=blue - 46 [label="Enter block"]; - 47 [label="Postponed enter to lambda"]; - subgraph cluster_14 { + 49 [label="Enter block"]; + 50 [label="Const: String()"]; + 51 [label="Jump: ^@run String()"]; + 52 [label="Stub" style="filled" fillcolor=gray]; + 53 [label="Exit block" style="filled" fillcolor=gray]; + } + 54 [label="Exit when branch result" style="filled" fillcolor=gray]; + 55 [label="Enter when branch result"]; + subgraph cluster_14 { + color=blue + 56 [label="Enter block"]; + 57 [label="Postponed enter to lambda"]; + subgraph cluster_15 { color=blue - 57 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_15 { + 67 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_16 { color=blue - 58 [label="Enter block"]; - 59 [label="Access variable R|/y|"]; - 60 [label="Type operator: (R|/y| as R|kotlin/String|)"]; - 61 [label="Const: String(...)"]; - 62 [label="Assignment: R|SubstitutionOverride|"]; - 63 [label="Exit block"]; + 68 [label="Enter block"]; + 69 [label="Access variable R|/y|"]; + 70 [label="Type operator: (R|/y| as R|kotlin/String|)"]; + 71 [label="Const: String(...)"]; + 72 [label="Assignment: R|SubstitutionOverride|"]; + 73 [label="Exit block"]; } - 64 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 74 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 48 [label="Postponed exit from lambda"]; - 49 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; - 50 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { + 58 [label="Postponed exit from lambda"]; + 59 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; + 60 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { (R|/y| as R|kotlin/String|) this@R|special/anonymous|.R|SubstitutionOverride| = String(...) } )"]; - 51 [label="Stub" style="filled" fillcolor=gray]; - 52 [label="Exit block" style="filled" fillcolor=gray]; + 61 [label="Stub" style="filled" fillcolor=gray]; + 62 [label="Exit block" style="filled" fillcolor=gray]; } - 53 [label="Exit when branch result" style="filled" fillcolor=gray]; - 54 [label="Exit when" style="filled" fillcolor=gray]; + 63 [label="Exit when branch result" style="filled" fillcolor=gray]; + 64 [label="Exit when" style="filled" fillcolor=gray]; } - 55 [label="Exit block" style="filled" fillcolor=gray]; + 65 [label="Exit block" style="filled" fillcolor=gray]; } - 56 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 66 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 23 [label="Postponed exit from lambda"]; - 24 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 25 [label="Variable declaration: lval x: R|kotlin/String|"]; - 26 [label="Access variable R|/y|"]; - 27 [label="Access variable R|kotlin/String.length#|"]; - 28 [label="Exit block"]; + 33 [label="Postponed exit from lambda"]; + 34 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 35 [label="Variable declaration: lval x: R|kotlin/String|"]; + 36 [label="Access variable R|/y|"]; + 37 [label="Access variable R|kotlin/String.length#|"]; + 38 [label="Exit block"]; } - 29 [label="Exit function test1" style="filled" fillcolor=red]; + 39 [label="Exit function test1" style="filled" fillcolor=red]; } - 18 -> {19}; - 19 -> {20}; - 20 -> {21}; - 21 -> {22}; - 22 -> {30 24}; - 22 -> {23} [style=dotted]; - 22 -> {30} [style=dashed]; - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {27}; - 27 -> {28}; 28 -> {29}; + 29 -> {30}; 30 -> {31}; 31 -> {32}; - 32 -> {33}; + 32 -> {40 34}; + 32 -> {33} [style=dotted]; + 32 -> {40} [style=dashed]; 33 -> {34}; 34 -> {35}; - 35 -> {45 36}; + 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; 40 -> {41}; - 41 -> {56}; - 41 -> {42} [style=dotted]; - 42 -> {43} [style=dotted]; - 43 -> {44} [style=dotted]; - 44 -> {54} [style=dotted]; - 45 -> {46}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {55 46}; 46 -> {47}; - 47 -> {49 57}; - 47 -> {48} [style=dotted]; - 47 -> {57} [style=dashed]; - 48 -> {49} [color=green]; + 47 -> {48}; + 48 -> {49}; 49 -> {50}; - 50 -> {56}; - 50 -> {51} [style=dotted]; + 50 -> {51}; + 51 -> {66}; 51 -> {52} [style=dotted]; 52 -> {53} [style=dotted]; 53 -> {54} [style=dotted]; - 54 -> {55} [style=dotted]; - 55 -> {56} [style=dotted]; - 56 -> {23}; - 57 -> {58}; - 58 -> {59}; + 54 -> {64} [style=dotted]; + 55 -> {56}; + 56 -> {57}; + 57 -> {59 67}; + 57 -> {58} [style=dotted]; + 57 -> {67} [style=dashed]; + 58 -> {59} [color=green]; 59 -> {60}; - 60 -> {61}; - 61 -> {62}; - 62 -> {63}; - 63 -> {64}; - 64 -> {48}; - - subgraph cluster_16 { - color=red - 65 [label="Enter function test2" style="filled" fillcolor=red]; - subgraph cluster_17 { - color=blue - 66 [label="Enter block"]; - 67 [label="Postponed enter to lambda"]; - subgraph cluster_18 { - color=blue - 75 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_19 { - color=blue - 76 [label="Enter block"]; - subgraph cluster_20 { - color=blue - 77 [label="Enter while loop"]; - subgraph cluster_21 { - color=blue - 78 [label="Enter loop condition"]; - 79 [label="Const: Boolean(true)"]; - 80 [label="Exit loop condition"]; - } - subgraph cluster_22 { - color=blue - 81 [label="Enter loop block"]; - subgraph cluster_23 { - color=blue - 82 [label="Enter block"]; - subgraph cluster_24 { - color=blue - 83 [label="Try expression enter"]; - subgraph cluster_25 { - color=blue - 84 [label="Try main block enter"]; - subgraph cluster_26 { - color=blue - 85 [label="Enter block"]; - 86 [label="Postponed enter to lambda"]; - subgraph cluster_27 { - color=blue - 107 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_28 { - color=blue - 108 [label="Enter block"]; - 109 [label="Const: String(...)"]; - 110 [label="Assignment: R|SubstitutionOverride|"]; - 111 [label="Exit block"]; - } - 112 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 87 [label="Postponed exit from lambda"]; - 88 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; - 89 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { - this@R|special/anonymous|.R|SubstitutionOverride| = String(...) -} -)"]; - 90 [label="Stub" style="filled" fillcolor=gray]; - 91 [label="Exit block" style="filled" fillcolor=gray]; - } - 92 [label="Try main block exit" style="filled" fillcolor=gray]; - } - subgraph cluster_29 { - color=blue - 93 [label="Catch enter"]; - 94 [label="Variable declaration: e: R|kotlin/Throwable|"]; - subgraph cluster_30 { - color=blue - 95 [label="Enter block"]; - 96 [label="Exit block"]; - } - 97 [label="Catch exit"]; - } - 98 [label="Try expression exit"]; - } - 99 [label="Exit block"]; - } - 100 [label="Exit loop block"]; - } - 101 [label="Exit whileloop" style="filled" fillcolor=gray]; - } - 102 [label="Function call: R|java/lang/Exception.Exception|()" style="filled" fillcolor=gray]; - 103 [label="Throw: throw R|java/lang/Exception.Exception|()" style="filled" fillcolor=gray]; - 104 [label="Stub" style="filled" fillcolor=gray]; - 105 [label="Exit block" style="filled" fillcolor=gray]; - } - 106 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 68 [label="Postponed exit from lambda"]; - 69 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 70 [label="Variable declaration: lval x: R|kotlin/String|"]; - 71 [label="Access variable R|/x|"]; - 72 [label="Access variable R|kotlin/String.length|"]; - 73 [label="Exit block"]; - } - 74 [label="Exit function test2" style="filled" fillcolor=red]; - } - 65 -> {66}; - 66 -> {67}; - 67 -> {75 69}; - 67 -> {68} [style=dotted]; - 67 -> {75} [style=dashed]; + 60 -> {66}; + 60 -> {61} [style=dotted]; + 61 -> {62} [style=dotted]; + 62 -> {63} [style=dotted]; + 63 -> {64} [style=dotted]; + 64 -> {65} [style=dotted]; + 65 -> {66} [style=dotted]; + 66 -> {33}; + 67 -> {68}; 68 -> {69}; 69 -> {70}; 70 -> {71}; 71 -> {72}; 72 -> {73}; 73 -> {74}; + 74 -> {58}; + + subgraph cluster_17 { + color=red + 75 [label="Enter function test2" style="filled" fillcolor=red]; + subgraph cluster_18 { + color=blue + 76 [label="Enter block"]; + 77 [label="Postponed enter to lambda"]; + subgraph cluster_19 { + color=blue + 85 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_20 { + color=blue + 86 [label="Enter block"]; + subgraph cluster_21 { + color=blue + 87 [label="Enter while loop"]; + subgraph cluster_22 { + color=blue + 88 [label="Enter loop condition"]; + 89 [label="Const: Boolean(true)"]; + 90 [label="Exit loop condition"]; + } + subgraph cluster_23 { + color=blue + 91 [label="Enter loop block"]; + subgraph cluster_24 { + color=blue + 92 [label="Enter block"]; + subgraph cluster_25 { + color=blue + 93 [label="Try expression enter"]; + subgraph cluster_26 { + color=blue + 94 [label="Try main block enter"]; + subgraph cluster_27 { + color=blue + 95 [label="Enter block"]; + 96 [label="Postponed enter to lambda"]; + subgraph cluster_28 { + color=blue + 117 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_29 { + color=blue + 118 [label="Enter block"]; + 119 [label="Const: String(...)"]; + 120 [label="Assignment: R|SubstitutionOverride|"]; + 121 [label="Exit block"]; + } + 122 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 97 [label="Postponed exit from lambda"]; + 98 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; + 99 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|SubstitutionOverride| = String(...) +} +)"]; + 100 [label="Stub" style="filled" fillcolor=gray]; + 101 [label="Exit block" style="filled" fillcolor=gray]; + } + 102 [label="Try main block exit" style="filled" fillcolor=gray]; + } + subgraph cluster_30 { + color=blue + 103 [label="Catch enter"]; + 104 [label="Variable declaration: e: R|kotlin/Throwable|"]; + subgraph cluster_31 { + color=blue + 105 [label="Enter block"]; + 106 [label="Exit block"]; + } + 107 [label="Catch exit"]; + } + 108 [label="Try expression exit"]; + } + 109 [label="Exit block"]; + } + 110 [label="Exit loop block"]; + } + 111 [label="Exit whileloop" style="filled" fillcolor=gray]; + } + 112 [label="Function call: R|java/lang/Exception.Exception|()" style="filled" fillcolor=gray]; + 113 [label="Throw: throw R|java/lang/Exception.Exception|()" style="filled" fillcolor=gray]; + 114 [label="Stub" style="filled" fillcolor=gray]; + 115 [label="Exit block" style="filled" fillcolor=gray]; + } + 116 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 78 [label="Postponed exit from lambda"]; + 79 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 80 [label="Variable declaration: lval x: R|kotlin/String|"]; + 81 [label="Access variable R|/x|"]; + 82 [label="Access variable R|kotlin/String.length|"]; + 83 [label="Exit block"]; + } + 84 [label="Exit function test2" style="filled" fillcolor=red]; + } 75 -> {76}; 76 -> {77}; - 77 -> {78}; + 77 -> {85 79}; + 77 -> {78} [style=dotted]; + 77 -> {85} [style=dashed]; 78 -> {79}; 79 -> {80}; 80 -> {81}; - 80 -> {101} [style=dotted]; 81 -> {82}; 82 -> {83}; - 83 -> {84 93}; - 84 -> {85}; + 83 -> {84}; 85 -> {86}; - 86 -> {88 107}; - 86 -> {87} [style=dotted]; - 86 -> {107} [style=dashed]; - 87 -> {88} [color=green]; + 86 -> {87}; + 87 -> {88}; 88 -> {89}; - 89 -> {106}; - 89 -> {90} [style=dotted]; - 90 -> {91} [style=dotted]; - 91 -> {92} [style=dotted]; - 92 -> {98 93} [style=dotted]; - 93 -> {94}; - 93 -> {74} [label=onUncaughtException]; + 89 -> {90}; + 90 -> {91}; + 90 -> {111} [style=dotted]; + 91 -> {92}; + 92 -> {93}; + 93 -> {94 103}; 94 -> {95}; 95 -> {96}; - 96 -> {97}; - 97 -> {98}; + 96 -> {98 117}; + 96 -> {97} [style=dotted]; + 96 -> {117} [style=dashed]; + 97 -> {98} [color=green]; 98 -> {99}; - 99 -> {100}; - 100 -> {78} [color=green style=dashed]; + 99 -> {116}; + 99 -> {100} [style=dotted]; + 100 -> {101} [style=dotted]; 101 -> {102} [style=dotted]; - 102 -> {103} [style=dotted]; - 103 -> {104} [style=dotted]; - 103 -> {74} [style=dotted] [label=onUncaughtException]; - 104 -> {105} [style=dotted]; - 105 -> {106} [style=dotted]; - 106 -> {68}; + 102 -> {108 103} [style=dotted]; + 103 -> {104}; + 103 -> {84} [label=onUncaughtException]; + 104 -> {105}; + 105 -> {106}; + 106 -> {107}; 107 -> {108}; 108 -> {109}; 109 -> {110}; - 110 -> {111}; - 111 -> {112}; - 112 -> {87}; + 110 -> {88} [color=green style=dashed]; + 111 -> {112} [style=dotted]; + 112 -> {113} [style=dotted]; + 113 -> {114} [style=dotted]; + 113 -> {84} [style=dotted] [label=onUncaughtException]; + 114 -> {115} [style=dotted]; + 115 -> {116} [style=dotted]; + 116 -> {78}; + 117 -> {118}; + 118 -> {119}; + 119 -> {120}; + 120 -> {121}; + 121 -> {122}; + 122 -> {97}; - subgraph cluster_31 { + subgraph cluster_32 { color=red - 113 [label="Enter function test3" style="filled" fillcolor=red]; - subgraph cluster_32 { + 123 [label="Enter function test3" style="filled" fillcolor=red]; + subgraph cluster_33 { color=blue - 114 [label="Enter block"]; - 115 [label="Variable declaration: lvar y: R|kotlin/String?|"]; - 116 [label="Const: String()"]; - 117 [label="Assignment: R|/y|"]; - 118 [label="Postponed enter to lambda"]; - subgraph cluster_33 { + 124 [label="Enter block"]; + 125 [label="Variable declaration: lvar y: R|kotlin/String?|"]; + 126 [label="Const: String()"]; + 127 [label="Assignment: R|/y|"]; + 128 [label="Postponed enter to lambda"]; + subgraph cluster_34 { color=blue - 127 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_34 { + 137 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_35 { color=blue - 128 [label="Enter block"]; - subgraph cluster_35 { + 138 [label="Enter block"]; + subgraph cluster_36 { color=blue - 129 [label="Enter when"]; - subgraph cluster_36 { - color=blue - 130 [label="Enter when branch condition "]; - 131 [label="Access variable R|/p|"]; - 132 [label="Function call: R|/p|.R|kotlin/Boolean.not|()" style="filled" fillcolor=yellow]; - 133 [label="Exit when branch condition"]; - } + 139 [label="Enter when"]; subgraph cluster_37 { color=blue - 134 [label="Enter when branch condition else"]; - 135 [label="Exit when branch condition"]; + 140 [label="Enter when branch condition "]; + 141 [label="Access variable R|/p|"]; + 142 [label="Function call: R|/p|.R|kotlin/Boolean.not|()" style="filled" fillcolor=yellow]; + 143 [label="Exit when branch condition"]; } - 136 [label="Enter when branch result"]; subgraph cluster_38 { color=blue - 137 [label="Enter block"]; - 138 [label="Const: String()"]; - 139 [label="Jump: ^@run String()"]; - 140 [label="Stub" style="filled" fillcolor=gray]; - 141 [label="Exit block" style="filled" fillcolor=gray]; + 144 [label="Enter when branch condition else"]; + 145 [label="Exit when branch condition"]; } - 142 [label="Exit when branch result" style="filled" fillcolor=gray]; - 143 [label="Enter when branch result"]; + 146 [label="Enter when branch result"]; subgraph cluster_39 { color=blue - 144 [label="Enter block"]; - 145 [label="Postponed enter to lambda"]; - subgraph cluster_40 { + 147 [label="Enter block"]; + 148 [label="Const: String()"]; + 149 [label="Jump: ^@run String()"]; + 150 [label="Stub" style="filled" fillcolor=gray]; + 151 [label="Exit block" style="filled" fillcolor=gray]; + } + 152 [label="Exit when branch result" style="filled" fillcolor=gray]; + 153 [label="Enter when branch result"]; + subgraph cluster_40 { + color=blue + 154 [label="Enter block"]; + 155 [label="Postponed enter to lambda"]; + subgraph cluster_41 { color=blue - 155 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_41 { + 165 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_42 { color=blue - 156 [label="Enter block"]; - 157 [label="Const: Null(null)"]; - 158 [label="Assignment: R|/y|"]; - 159 [label="Const: String(...)"]; - 160 [label="Assignment: R|SubstitutionOverride|"]; - 161 [label="Exit block"]; + 166 [label="Enter block"]; + 167 [label="Const: Null(null)"]; + 168 [label="Assignment: R|/y|"]; + 169 [label="Const: String(...)"]; + 170 [label="Assignment: R|SubstitutionOverride|"]; + 171 [label="Exit block"]; } - 162 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 172 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 146 [label="Postponed exit from lambda"]; - 147 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; - 148 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { + 156 [label="Postponed exit from lambda"]; + 157 [label="Function call: R|/build|(...)" style="filled" fillcolor=yellow]; + 158 [label="Jump: ^@run R|/build|( = build@fun R|Lateinit|.(): R|kotlin/Unit| { R|/y| = Null(null) this@R|special/anonymous|.R|SubstitutionOverride| = String(...) } )"]; - 149 [label="Stub" style="filled" fillcolor=gray]; - 150 [label="Exit block" style="filled" fillcolor=gray]; + 159 [label="Stub" style="filled" fillcolor=gray]; + 160 [label="Exit block" style="filled" fillcolor=gray]; } - 151 [label="Exit when branch result" style="filled" fillcolor=gray]; - 152 [label="Exit when" style="filled" fillcolor=gray]; + 161 [label="Exit when branch result" style="filled" fillcolor=gray]; + 162 [label="Exit when" style="filled" fillcolor=gray]; } - 153 [label="Exit block" style="filled" fillcolor=gray]; + 163 [label="Exit block" style="filled" fillcolor=gray]; } - 154 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 164 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 119 [label="Postponed exit from lambda"]; - 120 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 121 [label="Variable declaration: lval x: R|kotlin/String|"]; - 122 [label="Access variable R|/y|"]; - 123 [label="Smart cast: R|/y|"]; - 124 [label="Access variable R|kotlin/String.length|"]; - 125 [label="Exit block"]; + 129 [label="Postponed exit from lambda"]; + 130 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 131 [label="Variable declaration: lval x: R|kotlin/String|"]; + 132 [label="Access variable R|/y|"]; + 133 [label="Smart cast: R|/y|"]; + 134 [label="Access variable R|kotlin/String.length|"]; + 135 [label="Exit block"]; } - 126 [label="Exit function test3" style="filled" fillcolor=red]; + 136 [label="Exit function test3" style="filled" fillcolor=red]; } - 113 -> {114}; - 114 -> {115}; - 115 -> {116}; - 116 -> {117}; - 117 -> {118}; - 118 -> {127 120}; - 118 -> {119} [style=dotted]; - 118 -> {127} [style=dashed]; - 119 -> {120}; - 120 -> {121}; - 121 -> {122}; - 122 -> {123}; 123 -> {124}; 124 -> {125}; 125 -> {126}; + 126 -> {127}; 127 -> {128}; - 128 -> {129}; + 128 -> {137 130}; + 128 -> {129} [style=dotted]; + 128 -> {137} [style=dashed]; 129 -> {130}; 130 -> {131}; 131 -> {132}; 132 -> {133}; - 133 -> {143 134}; + 133 -> {134}; 134 -> {135}; 135 -> {136}; - 136 -> {137}; 137 -> {138}; 138 -> {139}; - 139 -> {154}; - 139 -> {140} [style=dotted]; - 140 -> {141} [style=dotted]; - 141 -> {142} [style=dotted]; - 142 -> {152} [style=dotted]; - 143 -> {144}; + 139 -> {140}; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {153 144}; 144 -> {145}; - 145 -> {147 155}; - 145 -> {146} [style=dotted]; - 145 -> {155} [style=dashed]; - 146 -> {147} [color=green]; + 145 -> {146}; + 146 -> {147}; 147 -> {148}; - 148 -> {154}; - 148 -> {149} [style=dotted]; + 148 -> {149}; + 149 -> {164}; 149 -> {150} [style=dotted]; 150 -> {151} [style=dotted]; 151 -> {152} [style=dotted]; - 152 -> {153} [style=dotted]; - 153 -> {154} [style=dotted]; - 154 -> {119}; - 155 -> {156}; - 156 -> {157}; + 152 -> {162} [style=dotted]; + 153 -> {154}; + 154 -> {155}; + 155 -> {157 165}; + 155 -> {156} [style=dotted]; + 155 -> {165} [style=dashed]; + 156 -> {157} [color=green]; 157 -> {158}; - 158 -> {159}; - 159 -> {160}; - 160 -> {161}; - 161 -> {162}; - 162 -> {146}; + 158 -> {164}; + 158 -> {159} [style=dotted]; + 159 -> {160} [style=dotted]; + 160 -> {161} [style=dotted]; + 161 -> {162} [style=dotted]; + 162 -> {163} [style=dotted]; + 163 -> {164} [style=dotted]; + 164 -> {129}; + 165 -> {166}; + 166 -> {167}; + 167 -> {168}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {156}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.fir.txt index 18334c4109d..80e11836ee0 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/postponedLambdaInReturn.fir.txt @@ -15,7 +15,13 @@ FILE: postponedLambdaInReturn.kt CallsInPlace(builder, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/builder|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + ^build R|/Lateinit.Lateinit|().R|kotlin/apply||>(R|/builder|).R|SubstitutionOverride| } public final val p: R|kotlin/Boolean| = Boolean(false) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.dot index 0c2f8ac3bd9..e84fa951ae9 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.dot @@ -9,100 +9,107 @@ digraph inAnonymousObject_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Enter anonymous object"]; subgraph cluster_2 { color=blue - 11 [label="Enter class " style="filled" fillcolor=red]; - 12 [label="Part of class initialization"]; - 13 [label="Part of class initialization"]; - 14 [label="Exit class " style="filled" fillcolor=red]; + 2 [label="Enter block"]; + 3 [label="Exit block"]; } - 3 [label="Exit anonymous object"]; - 4 [label="Exit anonymous object expression"]; - 5 [label="Variable declaration: lval obj: R||"]; - 6 [label="Access variable R|/obj|"]; - 7 [label="Function call: R|/obj|.R|/.run|()" style="filled" fillcolor=yellow]; - 8 [label="Function call: R|/d|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 9 [label="Exit block"]; + 4 [label="Enter anonymous object"]; + subgraph cluster_3 { + color=blue + 13 [label="Enter class " style="filled" fillcolor=red]; + 14 [label="Part of class initialization"]; + 15 [label="Part of class initialization"]; + 16 [label="Exit class " style="filled" fillcolor=red]; + } + 5 [label="Exit anonymous object"]; + 6 [label="Exit anonymous object expression"]; + 7 [label="Variable declaration: lval obj: R||"]; + 8 [label="Access variable R|/obj|"]; + 9 [label="Function call: R|/obj|.R|/.run|()" style="filled" fillcolor=yellow]; + 10 [label="Function call: R|/d|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 11 [label="Exit block"]; } - 10 [label="Exit function foo" style="filled" fillcolor=red]; + 12 [label="Exit function foo" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; - 1 -> {15 18 21 27} [color=red]; - 2 -> {3} [color=red]; - 2 -> {11} [color=green]; - 2 -> {11} [style=dashed]; + 2 -> {3}; 3 -> {4}; - 3 -> {15 27} [color=green]; - 3 -> {15 27} [style=dashed]; - 4 -> {5}; + 3 -> {37 40 43 49} [color=red]; + 4 -> {5} [color=red]; + 4 -> {13} [color=green]; + 4 -> {13} [style=dashed]; 5 -> {6}; + 5 -> {37 49} [color=green]; + 5 -> {37 49} [style=dashed]; 6 -> {7}; 7 -> {8}; 8 -> {9}; 9 -> {10}; - 11 -> {12} [color=green]; - 12 -> {13} [style=dotted]; - 12 -> {18} [color=green]; - 12 -> {18} [style=dashed]; - 13 -> {14} [style=dotted]; - 13 -> {21} [color=green]; - 13 -> {21} [style=dashed]; - 14 -> {3} [color=green]; - - subgraph cluster_3 { - color=red - 15 [label="Enter function " style="filled" fillcolor=red]; - 16 [label="Delegated constructor call: super()" style="filled" fillcolor=yellow]; - 17 [label="Exit function " style="filled" fillcolor=red]; - } - 15 -> {16}; - 16 -> {17}; + 10 -> {11}; + 11 -> {12}; + 13 -> {14} [color=green]; + 14 -> {15} [style=dotted]; + 14 -> {40} [color=green]; + 14 -> {40} [style=dashed]; + 15 -> {16} [style=dotted]; + 15 -> {43} [color=green]; + 15 -> {43} [style=dashed]; + 16 -> {5} [color=green]; subgraph cluster_4 { color=red - 18 [label="Enter property" style="filled" fillcolor=red]; - 19 [label="Access variable R|/a|"]; - 20 [label="Exit property" style="filled" fillcolor=red]; + 37 [label="Enter function " style="filled" fillcolor=red]; + 38 [label="Delegated constructor call: super()" style="filled" fillcolor=yellow]; + 39 [label="Exit function " style="filled" fillcolor=red]; } - 18 -> {19}; - 19 -> {20}; - 20 -> {13} [color=green]; + 37 -> {38}; + 38 -> {39}; subgraph cluster_5 { color=red - 21 [label="Enter init block" style="filled" fillcolor=red]; - subgraph cluster_6 { - color=blue - 22 [label="Enter block"]; - 23 [label="Access variable R|/b|"]; - 24 [label="Assignment: R|/.leaked|"]; - 25 [label="Exit block"]; - } - 26 [label="Exit init block" style="filled" fillcolor=red]; + 40 [label="Enter property" style="filled" fillcolor=red]; + 41 [label="Access variable R|/a|"]; + 42 [label="Exit property" style="filled" fillcolor=red]; } - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {14} [color=green]; + 40 -> {41}; + 41 -> {42}; + 42 -> {15} [color=green]; - subgraph cluster_7 { + subgraph cluster_6 { color=red - 27 [label="Enter function run" style="filled" fillcolor=red]; - subgraph cluster_8 { + 43 [label="Enter init block" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 28 [label="Enter block"]; - 29 [label="Function call: R|/c|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 30 [label="Exit block"]; + 44 [label="Enter block"]; + 45 [label="Access variable R|/b|"]; + 46 [label="Assignment: R|/.leaked|"]; + 47 [label="Exit block"]; } - 31 [label="Exit function run" style="filled" fillcolor=red]; + 48 [label="Exit init block" style="filled" fillcolor=red]; } - 27 -> {28}; - 28 -> {29}; - 29 -> {30}; - 30 -> {31}; + 43 -> {44}; + 44 -> {45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {16} [color=green]; + + subgraph cluster_8 { + color=red + 49 [label="Enter function run" style="filled" fillcolor=red]; + subgraph cluster_9 { + color=blue + 50 [label="Enter block"]; + 51 [label="Function call: R|/c|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 52 [label="Exit block"]; + } + 53 [label="Exit function run" style="filled" fillcolor=red]; + } + 49 -> {50}; + 50 -> {51}; + 51 -> {52}; + 52 -> {53}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.fir.txt index 713779ed95e..ccfb13747ad 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inAnonymousObject.fir.txt @@ -8,7 +8,16 @@ FILE: inAnonymousObject.kt CallsInPlace(d, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/a|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/b|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/c|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/d|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + lval obj: R|| = object : R|java/lang/Runnable| { private constructor(): R|| { super() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.dot index 259308ad1e8..bb59c2a5763 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.dot @@ -9,100 +9,107 @@ digraph inLocalClass_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Exit local class foo"]; - 3 [label="Function call: R|/LocalClass.LocalClass|()" style="filled" fillcolor=yellow]; - 4 [label="Function call: R|/LocalClass.LocalClass|().R|/run|()" style="filled" fillcolor=yellow]; - 5 [label="Function call: R|/e|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 6 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Exit local class foo"]; + 5 [label="Function call: R|/LocalClass.LocalClass|()" style="filled" fillcolor=yellow]; + 6 [label="Function call: R|/LocalClass.LocalClass|().R|/run|()" style="filled" fillcolor=yellow]; + 7 [label="Function call: R|/e|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 8 [label="Exit block"]; } - 7 [label="Exit function foo" style="filled" fillcolor=red]; + 9 [label="Exit function foo" style="filled" fillcolor=red]; } - subgraph cluster_2 { + subgraph cluster_3 { color=blue - 8 [label="Enter class LocalClass" style="filled" fillcolor=red]; - 9 [label="Part of class initialization"]; - 10 [label="Part of class initialization"]; - 11 [label="Exit class LocalClass" style="filled" fillcolor=red]; + 10 [label="Enter class LocalClass" style="filled" fillcolor=red]; + 11 [label="Part of class initialization"]; + 12 [label="Part of class initialization"]; + 13 [label="Exit class LocalClass" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; - 1 -> {12 15 21 27} [color=red]; 2 -> {3}; - 2 -> {15 27 8} [color=green]; - 2 -> {15 27 8} [style=dashed]; 3 -> {4}; + 3 -> {38 41 47 53} [color=red]; 4 -> {5}; + 4 -> {41 53 10} [color=green]; + 4 -> {41 53 10} [style=dashed]; 5 -> {6}; 6 -> {7}; - 8 -> {9} [color=green]; - 9 -> {10} [style=dotted]; - 9 -> {12} [color=green]; - 9 -> {12} [style=dashed]; - 10 -> {11} [style=dotted]; - 10 -> {21} [color=green]; - 10 -> {21} [style=dashed]; - - subgraph cluster_3 { - color=red - 12 [label="Enter property" style="filled" fillcolor=red]; - 13 [label="Access variable R|/a|"]; - 14 [label="Exit property" style="filled" fillcolor=red]; - } - 12 -> {13}; - 13 -> {14}; - 14 -> {10} [color=green]; + 7 -> {8}; + 8 -> {9}; + 10 -> {11} [color=green]; + 11 -> {12} [style=dotted]; + 11 -> {38} [color=green]; + 11 -> {38} [style=dashed]; + 12 -> {13} [style=dotted]; + 12 -> {47} [color=green]; + 12 -> {47} [style=dashed]; subgraph cluster_4 { color=red - 15 [label="Enter function " style="filled" fillcolor=red]; - 16 [label="Delegated constructor call: super()" style="filled" fillcolor=yellow]; - subgraph cluster_5 { - color=blue - 17 [label="Enter block"]; - 18 [label="Function call: R|/b|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 19 [label="Exit block"]; - } - 20 [label="Exit function " style="filled" fillcolor=red]; + 38 [label="Enter property" style="filled" fillcolor=red]; + 39 [label="Access variable R|/a|"]; + 40 [label="Exit property" style="filled" fillcolor=red]; } - 15 -> {16}; - 16 -> {17}; - 17 -> {18}; - 18 -> {19}; - 19 -> {20}; + 38 -> {39}; + 39 -> {40}; + 40 -> {12} [color=green]; - subgraph cluster_6 { + subgraph cluster_5 { color=red - 21 [label="Enter init block" style="filled" fillcolor=red]; - subgraph cluster_7 { + 41 [label="Enter function " style="filled" fillcolor=red]; + 42 [label="Delegated constructor call: super()" style="filled" fillcolor=yellow]; + subgraph cluster_6 { color=blue - 22 [label="Enter block"]; - 23 [label="Access variable R|/c|"]; - 24 [label="Assignment: R|/leaked|"]; - 25 [label="Exit block"]; + 43 [label="Enter block"]; + 44 [label="Function call: R|/b|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 45 [label="Exit block"]; } - 26 [label="Exit init block" style="filled" fillcolor=red]; + 46 [label="Exit function " style="filled" fillcolor=red]; } - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {26}; - 26 -> {11} [color=green]; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {46}; - subgraph cluster_8 { + subgraph cluster_7 { color=red - 27 [label="Enter function run" style="filled" fillcolor=red]; - subgraph cluster_9 { + 47 [label="Enter init block" style="filled" fillcolor=red]; + subgraph cluster_8 { color=blue - 28 [label="Enter block"]; - 29 [label="Function call: R|/d|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 30 [label="Exit block"]; + 48 [label="Enter block"]; + 49 [label="Access variable R|/c|"]; + 50 [label="Assignment: R|/leaked|"]; + 51 [label="Exit block"]; } - 31 [label="Exit function run" style="filled" fillcolor=red]; + 52 [label="Exit init block" style="filled" fillcolor=red]; } - 27 -> {28}; - 28 -> {29}; - 29 -> {30}; - 30 -> {31}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50}; + 50 -> {51}; + 51 -> {52}; + 52 -> {13} [color=green]; + + subgraph cluster_9 { + color=red + 53 [label="Enter function run" style="filled" fillcolor=red]; + subgraph cluster_10 { + color=blue + 54 [label="Enter block"]; + 55 [label="Function call: R|/d|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 56 [label="Exit block"]; + } + 57 [label="Exit function run" style="filled" fillcolor=red]; + } + 53 -> {54}; + 54 -> {55}; + 55 -> {56}; + 56 -> {57}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.fir.txt index b953228e47d..d892b67122d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalClass.fir.txt @@ -9,7 +9,17 @@ FILE: inLocalClass.kt CallsInPlace(e, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/a|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/b|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/c|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/d|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/e|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + local final class LocalClass : R|kotlin/Any| { public final val leakedVal: R|() -> kotlin/Unit| = R|/a| public get(): R|() -> kotlin/Unit| diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.dot index ea5ce340799..a51e6f82ef4 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.dot @@ -9,38 +9,45 @@ digraph inLocalFunction_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Local function declaration foo"]; - 3 [label="Function call: R|/localFun|()" style="filled" fillcolor=yellow]; - 4 [label="Function call: R|/b|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 5 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Local function declaration foo"]; + 5 [label="Function call: R|/localFun|()" style="filled" fillcolor=yellow]; + 6 [label="Function call: R|/b|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 7 [label="Exit block"]; } - 6 [label="Exit function foo" style="filled" fillcolor=red]; + 8 [label="Exit function foo" style="filled" fillcolor=red]; } - subgraph cluster_2 { + subgraph cluster_3 { color=blue - 7 [label="Enter function localFun" style="filled" fillcolor=red]; - subgraph cluster_3 { + 9 [label="Enter function localFun" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 8 [label="Enter block"]; - 9 [label="Access variable R|/a|"]; - 10 [label="Function call: R|/a|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 11 [label="Function call: R|/a|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 12 [label="Exit block"]; + 10 [label="Enter block"]; + 11 [label="Access variable R|/a|"]; + 12 [label="Function call: R|/a|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 13 [label="Function call: R|/a|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 14 [label="Exit block"]; } - 13 [label="Exit function localFun" style="filled" fillcolor=red]; + 15 [label="Exit function localFun" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; - 2 -> {7 3}; - 2 -> {7} [style=dashed]; + 2 -> {3}; 3 -> {4}; - 4 -> {5}; + 4 -> {9 5}; + 4 -> {9} [style=dashed]; 5 -> {6}; + 6 -> {7}; 7 -> {8}; - 8 -> {9}; 9 -> {10}; 10 -> {11}; 11 -> {12}; 12 -> {13}; + 13 -> {14}; + 14 -> {15}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.fir.txt index d1067512066..e11697913eb 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/inLocalFunction.fir.txt @@ -5,7 +5,13 @@ FILE: inLocalFunction.kt CallsInPlace(a, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/a|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + local final fun localFun(): R|kotlin/Unit| { R|/a|.R|SubstitutionOverride|() R|/a|.R|SubstitutionOverride|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.dot index fe5fce755c0..ffd0c1500af 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.dot @@ -25,64 +25,69 @@ digraph toLocalVariables_kt { 5 [label="Enter block"]; subgraph cluster_4 { color=blue - 6 [label="Enter when"]; - subgraph cluster_5 { - color=blue - 7 [label="Enter when branch condition "]; - 8 [label="Const: Boolean(true)"]; - 9 [label="Exit when branch condition"]; - } + 6 [label="Enter block"]; + 7 [label="Exit block"]; + } + subgraph cluster_5 { + color=blue + 8 [label="Enter when"]; subgraph cluster_6 { color=blue - 10 [label="Enter when branch condition else"]; + 9 [label="Enter when branch condition "]; + 10 [label="Const: Boolean(true)"]; 11 [label="Exit when branch condition"]; } - 12 [label="Enter when branch result"]; subgraph cluster_7 { color=blue - 13 [label="Enter block"]; - 14 [label="Access variable R|/y|"]; - 15 [label="Variable declaration: lval yCopy: R|() -> kotlin/Unit|"]; - 16 [label="Function call: R|/yCopy|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 17 [label="Exit block"]; + 12 [label="Enter when branch condition else"]; + 13 [label="Exit when branch condition"]; } - 18 [label="Exit when branch result"]; - 19 [label="Enter when branch result"]; + 14 [label="Enter when branch result"]; subgraph cluster_8 { color=blue - 20 [label="Enter block"]; - 21 [label="Access variable R|/x|"]; - 22 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 23 [label="Exit block"]; + 15 [label="Enter block"]; + 16 [label="Access variable R|/y|"]; + 17 [label="Variable declaration: lval yCopy: R|() -> kotlin/Unit|"]; + 18 [label="Function call: R|/yCopy|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 19 [label="Exit block"]; } - 24 [label="Exit when branch result"]; - 25 [label="Exit when"]; + 20 [label="Exit when branch result"]; + 21 [label="Enter when branch result"]; + subgraph cluster_9 { + color=blue + 22 [label="Enter block"]; + 23 [label="Access variable R|/x|"]; + 24 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 25 [label="Exit block"]; + } + 26 [label="Exit when branch result"]; + 27 [label="Exit when"]; } - 26 [label="Variable declaration: lval zCopy: R|() -> kotlin/Unit|"]; - 27 [label="Access variable R|/z|"]; - 28 [label="Assignment: R|/zCopy|"]; - 29 [label="Function call: R|/zCopy|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 30 [label="Exit block"]; + 28 [label="Variable declaration: lval zCopy: R|() -> kotlin/Unit|"]; + 29 [label="Access variable R|/z|"]; + 30 [label="Assignment: R|/zCopy|"]; + 31 [label="Function call: R|/zCopy|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 32 [label="Exit block"]; } - 31 [label="Exit function foo" style="filled" fillcolor=red]; + 33 [label="Exit function foo" style="filled" fillcolor=red]; } 4 -> {5}; 5 -> {6}; 6 -> {7}; 7 -> {8}; 8 -> {9}; - 9 -> {19 10}; + 9 -> {10}; 10 -> {11}; - 11 -> {12}; + 11 -> {21 12}; 12 -> {13}; 13 -> {14}; 14 -> {15}; 15 -> {16}; 16 -> {17}; 17 -> {18}; - 18 -> {25}; + 18 -> {19}; 19 -> {20}; - 20 -> {21}; + 20 -> {27}; 21 -> {22}; 22 -> {23}; 23 -> {24}; @@ -93,5 +98,7 @@ digraph toLocalVariables_kt { 28 -> {29}; 29 -> {30}; 30 -> {31}; + 31 -> {32}; + 32 -> {33}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.fir.txt index eb64ce50bb3..678e1d710d8 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace/toLocalVariables.fir.txt @@ -9,7 +9,15 @@ FILE: toLocalVariables.kt CallsInPlace(z, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/y|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/z|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + when () { Boolean(true) -> { R|/bar|(R|/x|) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.fir.txt new file mode 100644 index 00000000000..c064ce75f79 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.fir.txt @@ -0,0 +1,29 @@ +FILE: noOptIn.kt + public final fun checkIsString(x: R|kotlin/Any|): R|kotlin/Boolean| + [R|Contract description] + < + Returns(TRUE) -> x is kotlin/String + Returns(FALSE) -> x !is kotlin/String + > + { + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|)) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(false)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| !is R|kotlin/String|)) + } + ) + } + + ^checkIsString (R|/x| is R|kotlin/String|) + } + public final fun test(x: R|kotlin/Any|): R|kotlin/Unit| { + when () { + R|/checkIsString|(R|/x|) -> { + R|/x|.R|kotlin/String.length| + } + else -> { + R|/x|.# + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt new file mode 100644 index 00000000000..cc40721af62 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt @@ -0,0 +1,17 @@ +import kotlin.contracts.* + +fun checkIsString(x: Any): Boolean { + contract { + returns(true) implies (x is String) + returns(false) implies (x !is String) + } + return x is String +} + +fun test(x: Any) { + if (checkIsString(x)) { + x.length // OK + } else { + x.length // Error + } +} diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/notNull.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/notNull.fir.txt index 48d6bcd41bb..752d4f94a8a 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/notNull.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/notNull.fir.txt @@ -5,7 +5,13 @@ FILE: notNull.kt Returns(NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Null(null)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + when () { Boolean(true) -> { throw Q|java/lang|.R|java/lang/IllegalArgumentException.IllegalArgumentException|() @@ -20,7 +26,13 @@ FILE: notNull.kt Returns(WILDCARD) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + when () { ==(R|/x|, Null(null)) -> { ^bar R|/x| @@ -35,6 +47,12 @@ FILE: notNull.kt Returns(NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Null(null)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^baz R|/x| } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.fir.txt index 6b2754ed1af..2f4329a2f2b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.fir.txt @@ -5,7 +5,13 @@ FILE: propertyGetter.kt Returns(TRUE) -> this != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(this@R|/isNotNull|, Null(null))) + } + ) + } + ^isNotNull !=(this@R|/isNotNull|, Null(null)) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final val R|kotlin/Any?|.isNotNull: R|kotlin/Boolean| @@ -15,6 +21,12 @@ FILE: propertyGetter.kt Returns(TRUE) -> this != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(this@R|/isNotNull|, Null(null))) + } + ) + } + ^ !=(this@R|/isNotNull|, Null(null)) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.fir.txt new file mode 100644 index 00000000000..b84973f5040 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.fir.txt @@ -0,0 +1,31 @@ +FILE: redundantConditions.kt + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun testAlwaysNotNull(x: R|kotlin/String?|): R|kotlin/Any?| + [R|Contract description] + < + Returns(NOT_NULL) -> x is kotlin/String && x != null + > + { + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|) && !=(R|/x|, Null(null))) + } + ) + } + + ^testAlwaysNotNull R|/x| + } + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun testAlwaysAny(x: R|kotlin/String?|): R|kotlin/Any?| + [R|Contract description] + < + Returns(NOT_NULL) -> x is kotlin/String? || x is kotlin/Any? + > + { + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String?|) || (R|/x| is R|kotlin/Any?|)) + } + ) + } + + ^testAlwaysAny R|/x| + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt new file mode 100644 index 00000000000..0d56b42a8ec --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt @@ -0,0 +1,20 @@ +// !OPT_IN: kotlin.RequiresOptIn +import kotlin.contracts.* + +@OptIn(ExperimentalContracts::class) +fun testAlwaysNotNull(x: String?): Any? { + contract { + returnsNotNull() implies (x is String && x != null) + } + + return x +} + +@OptIn(ExperimentalContracts::class) +fun testAlwaysAny(x: String?): Any? { + contract { + returnsNotNull() implies (x is String? || x is Any?) + } + + return x +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot index 73af71eea5c..4114a4f34d6 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.dot @@ -9,124 +9,138 @@ digraph atLeastOnce_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Exit block"]; } - 4 [label="Exit function inlineRun" style="filled" fillcolor=red]; + 6 [label="Exit function inlineRun" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; - - subgraph cluster_2 { - color=red - 5 [label="Enter function myRun" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 6 [label="Enter block"]; - 7 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 8 [label="Exit block"]; - } - 9 [label="Exit function myRun" style="filled" fillcolor=red]; - } + 4 -> {5}; 5 -> {6}; - 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - subgraph cluster_4 { + subgraph cluster_3 { color=red - 10 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_5 { + 15 [label="Enter function myRun" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 11 [label="Enter block"]; - 12 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 13 [label="Postponed enter to lambda"]; - subgraph cluster_6 { + 16 [label="Enter block"]; + subgraph cluster_5 { color=blue - 20 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_7 { - color=blue - 21 [label="Enter block"]; - 22 [label="Const: Int(1)"]; - 23 [label="Assignment: R|/x|"]; - 24 [label="Exit block"]; - } - 25 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 17 [label="Enter block"]; + 18 [label="Exit block"]; } - 14 [label="Postponed exit from lambda"]; - 15 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; - 16 [label="Access variable R|/x|"]; - 17 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; + 19 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 19 [label="Exit function test_1" style="filled" fillcolor=red]; + 21 [label="Exit function myRun" style="filled" fillcolor=red]; } - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {20 15}; - 13 -> {14} [style=dotted]; - 13 -> {20} [style=dashed]; - 14 -> {15}; - 14 -> {13} [color=green style=dashed]; 15 -> {16}; 16 -> {17}; 17 -> {18}; 18 -> {19}; + 19 -> {20}; 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {14}; - subgraph cluster_8 { + subgraph cluster_6 { color=red - 26 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_9 { + 30 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 27 [label="Enter block"]; - 28 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 29 [label="Postponed enter to lambda"]; - subgraph cluster_10 { + 31 [label="Enter block"]; + 32 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 33 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 36 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_11 { + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 37 [label="Enter block"]; - 38 [label="Const: Int(1)"]; - 39 [label="Assignment: R|/x|"]; - 40 [label="Exit block"]; + 41 [label="Enter block"]; + 42 [label="Const: Int(1)"]; + 43 [label="Assignment: R|/x|"]; + 44 [label="Exit block"]; } - 41 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 45 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 30 [label="Postponed exit from lambda"]; - 31 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; - 32 [label="Access variable R|/x|"]; - 33 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 34 [label="Exit block"]; + 34 [label="Postponed exit from lambda"]; + 35 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; + 36 [label="Access variable R|/x|"]; + 37 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 38 [label="Exit block"]; } - 35 [label="Exit function test_2" style="filled" fillcolor=red]; + 39 [label="Exit function test_1" style="filled" fillcolor=red]; } - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {36 31}; - 29 -> {30} [style=dotted]; - 29 -> {36} [style=dashed]; 30 -> {31}; - 30 -> {29} [color=green style=dashed]; 31 -> {32}; 32 -> {33}; - 33 -> {34}; + 33 -> {40 35}; + 33 -> {34} [style=dotted]; + 33 -> {40} [style=dashed]; 34 -> {35}; + 34 -> {33} [color=green style=dashed]; + 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; 40 -> {41}; - 41 -> {30}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {34}; + + subgraph cluster_10 { + color=red + 46 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_11 { + color=blue + 47 [label="Enter block"]; + 48 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 49 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 56 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 57 [label="Enter block"]; + 58 [label="Const: Int(1)"]; + 59 [label="Assignment: R|/x|"]; + 60 [label="Exit block"]; + } + 61 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 50 [label="Postponed exit from lambda"]; + 51 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; + 52 [label="Access variable R|/x|"]; + 53 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 54 [label="Exit block"]; + } + 55 [label="Exit function test_2" style="filled" fillcolor=red]; + } + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {56 51}; + 49 -> {50} [style=dotted]; + 49 -> {56} [style=dashed]; + 50 -> {51}; + 50 -> {49} [color=green style=dashed]; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {50}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.fir.txt index 5d3524b8691..611cc05516b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.fir.txt @@ -1,20 +1,32 @@ FILE: atLeastOnce.kt - public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } - public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } public final fun test_1(): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.kt index bbbd5783b9f..73904d5cff1 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atLeastOnce.kt @@ -2,6 +2,7 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) inline fun inlineRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) @@ -9,6 +10,7 @@ inline fun inlineRun(block: () -> Unit) { block() } +@OptIn(ExperimentalContracts::class) fun myRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.dot index 80da72f5bb2..88904d625b7 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.dot @@ -9,120 +9,134 @@ digraph atMostOnce_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Exit block"]; } - 4 [label="Exit function inlineRun" style="filled" fillcolor=red]; + 6 [label="Exit function inlineRun" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; - - subgraph cluster_2 { - color=red - 5 [label="Enter function myRun" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 6 [label="Enter block"]; - 7 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 8 [label="Exit block"]; - } - 9 [label="Exit function myRun" style="filled" fillcolor=red]; - } + 4 -> {5}; 5 -> {6}; - 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - subgraph cluster_4 { + subgraph cluster_3 { color=red - 10 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_5 { + 15 [label="Enter function myRun" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 11 [label="Enter block"]; - 12 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 13 [label="Postponed enter to lambda"]; - subgraph cluster_6 { + 16 [label="Enter block"]; + subgraph cluster_5 { color=blue - 20 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_7 { - color=blue - 21 [label="Enter block"]; - 22 [label="Const: Int(1)"]; - 23 [label="Assignment: R|/x|"]; - 24 [label="Exit block"]; - } - 25 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 17 [label="Enter block"]; + 18 [label="Exit block"]; } - 14 [label="Postponed exit from lambda"]; - 15 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; - 16 [label="Access variable R|/x|"]; - 17 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; + 19 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 19 [label="Exit function test_1" style="filled" fillcolor=red]; + 21 [label="Exit function myRun" style="filled" fillcolor=red]; } - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {14 20 15}; - 13 -> {20} [style=dashed]; - 14 -> {15}; 15 -> {16}; 16 -> {17}; 17 -> {18}; 18 -> {19}; + 19 -> {20}; 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {14}; - subgraph cluster_8 { + subgraph cluster_6 { color=red - 26 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_9 { + 30 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 27 [label="Enter block"]; - 28 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 29 [label="Postponed enter to lambda"]; - subgraph cluster_10 { + 31 [label="Enter block"]; + 32 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 33 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 36 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_11 { + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 37 [label="Enter block"]; - 38 [label="Const: Int(1)"]; - 39 [label="Assignment: R|/x|"]; - 40 [label="Exit block"]; + 41 [label="Enter block"]; + 42 [label="Const: Int(1)"]; + 43 [label="Assignment: R|/x|"]; + 44 [label="Exit block"]; } - 41 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 45 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 30 [label="Postponed exit from lambda"]; - 31 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; - 32 [label="Access variable R|/x|"]; - 33 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 34 [label="Exit block"]; + 34 [label="Postponed exit from lambda"]; + 35 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; + 36 [label="Access variable R|/x|"]; + 37 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 38 [label="Exit block"]; } - 35 [label="Exit function test_2" style="filled" fillcolor=red]; + 39 [label="Exit function test_1" style="filled" fillcolor=red]; } - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {30 36 31}; - 29 -> {36} [style=dashed]; 30 -> {31}; 31 -> {32}; 32 -> {33}; - 33 -> {34}; + 33 -> {34 40 35}; + 33 -> {40} [style=dashed]; 34 -> {35}; + 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; 40 -> {41}; - 41 -> {30}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {34}; + + subgraph cluster_10 { + color=red + 46 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_11 { + color=blue + 47 [label="Enter block"]; + 48 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 49 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 56 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 57 [label="Enter block"]; + 58 [label="Const: Int(1)"]; + 59 [label="Assignment: R|/x|"]; + 60 [label="Exit block"]; + } + 61 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 50 [label="Postponed exit from lambda"]; + 51 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; + 52 [label="Access variable R|/x|"]; + 53 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 54 [label="Exit block"]; + } + 55 [label="Exit function test_2" style="filled" fillcolor=red]; + } + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50 56 51}; + 49 -> {56} [style=dashed]; + 50 -> {51}; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {50}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.fir.txt index a6da9471eef..107aaf9ac1b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.fir.txt @@ -1,20 +1,32 @@ FILE: atMostOnce.kt - public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } - public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } public final fun test_1(): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.kt index aed438bd621..6d86474277d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/atMostOnce.kt @@ -2,6 +2,7 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) inline fun inlineRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) @@ -9,6 +10,7 @@ inline fun inlineRun(block: () -> Unit) { block() } +@OptIn(ExperimentalContracts::class) fun myRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.dot index 41b0c98bfe4..d18720e0795 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.dot @@ -9,123 +9,144 @@ digraph contractsUsage_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Access variable R|/x|"]; - 3 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 4 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Access variable R|/x|"]; + 5 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 6 [label="Exit block"]; } - 5 [label="Exit function bar" style="filled" fillcolor=red]; + 7 [label="Exit function bar" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; 4 -> {5}; - - subgraph cluster_2 { - color=red - 6 [label="Enter function baz" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 7 [label="Enter block"]; - subgraph cluster_4 { - color=blue - 8 [label="Enter when"]; - subgraph cluster_5 { - color=blue - 9 [label="Enter when branch condition "]; - 10 [label="Const: Boolean(true)"]; - 11 [label="Exit when branch condition"]; - } - 12 [label="Synthetic else branch"]; - 13 [label="Enter when branch result"]; - subgraph cluster_6 { - color=blue - 14 [label="Enter block"]; - 15 [label="Access variable this@R|/baz|"]; - 16 [label="Function call: this@R|/baz|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 17 [label="Exit block"]; - } - 18 [label="Exit when branch result"]; - 19 [label="Exit when"]; - } - 20 [label="Exit block"]; - } - 21 [label="Exit function baz" style="filled" fillcolor=red]; - } + 5 -> {6}; 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - 9 -> {10}; - 10 -> {11}; - 11 -> {13 12}; - 12 -> {19}; - 13 -> {14}; - 14 -> {15}; - 15 -> {16}; + + subgraph cluster_3 { + color=red + 16 [label="Enter function baz" style="filled" fillcolor=red]; + subgraph cluster_4 { + color=blue + 17 [label="Enter block"]; + subgraph cluster_5 { + color=blue + 18 [label="Enter block"]; + 19 [label="Exit block"]; + } + subgraph cluster_6 { + color=blue + 20 [label="Enter when"]; + subgraph cluster_7 { + color=blue + 21 [label="Enter when branch condition "]; + 22 [label="Const: Boolean(true)"]; + 23 [label="Exit when branch condition"]; + } + 24 [label="Synthetic else branch"]; + 25 [label="Enter when branch result"]; + subgraph cluster_8 { + color=blue + 26 [label="Enter block"]; + 27 [label="Access variable this@R|/baz|"]; + 28 [label="Function call: this@R|/baz|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 29 [label="Exit block"]; + } + 30 [label="Exit when branch result"]; + 31 [label="Exit when"]; + } + 32 [label="Exit block"]; + } + 33 [label="Exit function baz" style="filled" fillcolor=red]; + } 16 -> {17}; 17 -> {18}; 18 -> {19}; 19 -> {20}; 20 -> {21}; - - subgraph cluster_7 { - color=red - 22 [label="Enter function foo" style="filled" fillcolor=red]; - subgraph cluster_8 { - color=blue - 23 [label="Enter block"]; - subgraph cluster_9 { - color=blue - 24 [label="Enter when"]; - subgraph cluster_10 { - color=blue - 25 [label="Enter when branch condition "]; - 26 [label="Const: Boolean(true)"]; - 27 [label="Exit when branch condition"]; - } - 28 [label="Synthetic else branch"]; - 29 [label="Enter when branch result"]; - subgraph cluster_11 { - color=blue - 30 [label="Enter block"]; - 31 [label="Access variable R|/x|"]; - 32 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 33 [label="Access variable R|/y|"]; - 34 [label="Function call: R|/y|.R|/baz|()" style="filled" fillcolor=yellow]; - 35 [label="Jump: ^foo Unit"]; - 36 [label="Stub" style="filled" fillcolor=gray]; - 37 [label="Exit block" style="filled" fillcolor=gray]; - } - 38 [label="Exit when branch result" style="filled" fillcolor=gray]; - 39 [label="Exit when"]; - } - 40 [label="Access variable R|/x|"]; - 41 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 42 [label="Exit block"]; - } - 43 [label="Exit function foo" style="filled" fillcolor=red]; - } + 21 -> {22}; 22 -> {23}; - 23 -> {24}; - 24 -> {25}; + 23 -> {25 24}; + 24 -> {31}; 25 -> {26}; 26 -> {27}; - 27 -> {29 28}; - 28 -> {39}; + 27 -> {28}; + 28 -> {29}; 29 -> {30}; 30 -> {31}; 31 -> {32}; 32 -> {33}; - 33 -> {34}; - 34 -> {35}; - 35 -> {43}; - 35 -> {36} [style=dotted]; - 36 -> {37} [style=dotted]; - 37 -> {38} [style=dotted]; - 38 -> {39} [style=dotted]; - 39 -> {40}; - 40 -> {41}; - 41 -> {42}; + + subgraph cluster_9 { + color=red + 42 [label="Enter function foo" style="filled" fillcolor=red]; + subgraph cluster_10 { + color=blue + 43 [label="Enter block"]; + subgraph cluster_11 { + color=blue + 44 [label="Enter block"]; + 45 [label="Exit block"]; + } + subgraph cluster_12 { + color=blue + 46 [label="Enter when"]; + subgraph cluster_13 { + color=blue + 47 [label="Enter when branch condition "]; + 48 [label="Const: Boolean(true)"]; + 49 [label="Exit when branch condition"]; + } + 50 [label="Synthetic else branch"]; + 51 [label="Enter when branch result"]; + subgraph cluster_14 { + color=blue + 52 [label="Enter block"]; + 53 [label="Access variable R|/x|"]; + 54 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 55 [label="Access variable R|/y|"]; + 56 [label="Function call: R|/y|.R|/baz|()" style="filled" fillcolor=yellow]; + 57 [label="Jump: ^foo Unit"]; + 58 [label="Stub" style="filled" fillcolor=gray]; + 59 [label="Exit block" style="filled" fillcolor=gray]; + } + 60 [label="Exit when branch result" style="filled" fillcolor=gray]; + 61 [label="Exit when"]; + } + 62 [label="Access variable R|/x|"]; + 63 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 64 [label="Exit block"]; + } + 65 [label="Exit function foo" style="filled" fillcolor=red]; + } 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {51 50}; + 50 -> {61}; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 55 -> {56}; + 56 -> {57}; + 57 -> {65}; + 57 -> {58} [style=dotted]; + 58 -> {59} [style=dotted]; + 59 -> {60} [style=dotted]; + 60 -> {61} [style=dotted]; + 61 -> {62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.fir.txt index 16f4ea50de9..5e72d84256d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.fir.txt @@ -1,20 +1,32 @@ FILE: contractsUsage.kt - @R|kotlin/contracts/ExperimentalContracts|() public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() } - @R|kotlin/contracts/ExperimentalContracts|() public final fun R|() -> kotlin/Unit|.baz(): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun R|() -> kotlin/Unit|.baz(): R|kotlin/Unit| [R|Contract description] < CallsInPlace(this, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(this@R|/baz|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + when () { Boolean(true) -> { this@R|/baz|.R|SubstitutionOverride|() @@ -22,14 +34,21 @@ FILE: contractsUsage.kt } } - @R|kotlin/contracts/ExperimentalContracts|() public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, AT_LEAST_ONCE) CallsInPlace(y, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/y|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + when () { Boolean(true) -> { R|/x|.R|SubstitutionOverride|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.kt index d296135048d..9cbe2bbe38c 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/contractsUsage.kt @@ -1,7 +1,7 @@ // !DUMP_CFG import kotlin.contracts.* -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun bar(x: () -> Unit) { contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) @@ -10,7 +10,7 @@ fun bar(x: () -> Unit) { x.invoke() } -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun (() -> Unit).baz() { contract { callsInPlace(this@baz, InvocationKind.AT_MOST_ONCE) @@ -21,7 +21,7 @@ fun (() -> Unit).baz() { } } -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun foo(x: () -> Unit, y: () -> Unit) { contract { callsInPlace(x, InvocationKind.AT_LEAST_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.dot index 914719beb02..3b361fbca8d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.dot @@ -9,122 +9,136 @@ digraph exactlyOnce_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Exit block"]; } - 4 [label="Exit function inlineRun" style="filled" fillcolor=red]; + 6 [label="Exit function inlineRun" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; - - subgraph cluster_2 { - color=red - 5 [label="Enter function myRun" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 6 [label="Enter block"]; - 7 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 8 [label="Exit block"]; - } - 9 [label="Exit function myRun" style="filled" fillcolor=red]; - } + 4 -> {5}; 5 -> {6}; - 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - subgraph cluster_4 { + subgraph cluster_3 { color=red - 10 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_5 { + 15 [label="Enter function myRun" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 11 [label="Enter block"]; - 12 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 13 [label="Postponed enter to lambda"]; - subgraph cluster_6 { + 16 [label="Enter block"]; + subgraph cluster_5 { color=blue - 20 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_7 { - color=blue - 21 [label="Enter block"]; - 22 [label="Const: Int(1)"]; - 23 [label="Assignment: R|/x|"]; - 24 [label="Exit block"]; - } - 25 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 17 [label="Enter block"]; + 18 [label="Exit block"]; } - 14 [label="Postponed exit from lambda"]; - 15 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; - 16 [label="Access variable R|/x|"]; - 17 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; + 19 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 19 [label="Exit function test_1" style="filled" fillcolor=red]; + 21 [label="Exit function myRun" style="filled" fillcolor=red]; } - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {20 15}; - 13 -> {14} [style=dotted]; - 13 -> {20} [style=dashed]; - 14 -> {15}; 15 -> {16}; 16 -> {17}; 17 -> {18}; 18 -> {19}; + 19 -> {20}; 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {14}; - subgraph cluster_8 { + subgraph cluster_6 { color=red - 26 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_9 { + 30 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 27 [label="Enter block"]; - 28 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 29 [label="Postponed enter to lambda"]; - subgraph cluster_10 { + 31 [label="Enter block"]; + 32 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 33 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 36 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_11 { + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 37 [label="Enter block"]; - 38 [label="Const: Int(1)"]; - 39 [label="Assignment: R|/x|"]; - 40 [label="Exit block"]; + 41 [label="Enter block"]; + 42 [label="Const: Int(1)"]; + 43 [label="Assignment: R|/x|"]; + 44 [label="Exit block"]; } - 41 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 45 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 30 [label="Postponed exit from lambda"]; - 31 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; - 32 [label="Access variable R|/x|"]; - 33 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 34 [label="Exit block"]; + 34 [label="Postponed exit from lambda"]; + 35 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; + 36 [label="Access variable R|/x|"]; + 37 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 38 [label="Exit block"]; } - 35 [label="Exit function test_2" style="filled" fillcolor=red]; + 39 [label="Exit function test_1" style="filled" fillcolor=red]; } - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {36 31}; - 29 -> {30} [style=dotted]; - 29 -> {36} [style=dashed]; 30 -> {31}; 31 -> {32}; 32 -> {33}; - 33 -> {34}; + 33 -> {40 35}; + 33 -> {34} [style=dotted]; + 33 -> {40} [style=dashed]; 34 -> {35}; + 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; 40 -> {41}; - 41 -> {30}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {34}; + + subgraph cluster_10 { + color=red + 46 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_11 { + color=blue + 47 [label="Enter block"]; + 48 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 49 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 56 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 57 [label="Enter block"]; + 58 [label="Const: Int(1)"]; + 59 [label="Assignment: R|/x|"]; + 60 [label="Exit block"]; + } + 61 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 50 [label="Postponed exit from lambda"]; + 51 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; + 52 [label="Access variable R|/x|"]; + 53 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 54 [label="Exit block"]; + } + 55 [label="Exit function test_2" style="filled" fillcolor=red]; + } + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {56 51}; + 49 -> {50} [style=dotted]; + 49 -> {56} [style=dashed]; + 50 -> {51}; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {50}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.fir.txt index a8c412a251f..83ad0859097 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.fir.txt @@ -1,20 +1,32 @@ FILE: exactlyOnce.kt - public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } - public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } public final fun test_1(): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.kt index bb304c78ecc..5c2d9c40bcd 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/exactlyOnce.kt @@ -2,6 +2,7 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) inline fun inlineRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -9,6 +10,7 @@ inline fun inlineRun(block: () -> Unit) { block() } +@OptIn(ExperimentalContracts::class) fun myRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.dot index 382eb4b226d..f559115dea3 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.dot @@ -11,221 +11,222 @@ digraph flow_kt { 1 [label="Enter block"]; subgraph cluster_2 { color=blue - 2 [label="Enter when"]; - subgraph cluster_3 { - color=blue - 3 [label="Enter when branch condition "]; - 4 [label="Const: Boolean(true)"]; - 5 [label="Exit when branch condition"]; - } - 6 [label="Synthetic else branch"]; - 7 [label="Enter when branch result"]; + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + subgraph cluster_3 { + color=blue + 4 [label="Enter when"]; subgraph cluster_4 { color=blue - 8 [label="Enter block"]; - 9 [label="Access variable R|/x|"]; - 10 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 11 [label="Jump: ^bar Unit"]; - 12 [label="Stub" style="filled" fillcolor=gray]; - 13 [label="Exit block" style="filled" fillcolor=gray]; + 5 [label="Enter when branch condition "]; + 6 [label="Const: Boolean(true)"]; + 7 [label="Exit when branch condition"]; } - 14 [label="Exit when branch result" style="filled" fillcolor=gray]; - 15 [label="Exit when"]; + 8 [label="Synthetic else branch"]; + 9 [label="Enter when branch result"]; + subgraph cluster_5 { + color=blue + 10 [label="Enter block"]; + 11 [label="Access variable R|/x|"]; + 12 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 13 [label="Jump: ^bar Unit"]; + 14 [label="Stub" style="filled" fillcolor=gray]; + 15 [label="Exit block" style="filled" fillcolor=gray]; + } + 16 [label="Exit when branch result" style="filled" fillcolor=gray]; + 17 [label="Exit when"]; } - 16 [label="Access variable R|/x|"]; - 17 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; + 18 [label="Access variable R|/x|"]; + 19 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 19 [label="Exit function bar" style="filled" fillcolor=red]; + 21 [label="Exit function bar" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; 4 -> {5}; - 5 -> {7 6}; - 6 -> {15}; - 7 -> {8}; - 8 -> {9}; + 5 -> {6}; + 6 -> {7}; + 7 -> {9 8}; + 8 -> {17}; 9 -> {10}; 10 -> {11}; - 11 -> {19}; - 11 -> {12} [style=dotted]; - 12 -> {13} [style=dotted]; + 11 -> {12}; + 12 -> {13}; + 13 -> {21}; 13 -> {14} [style=dotted]; 14 -> {15} [style=dotted]; - 15 -> {16}; - 16 -> {17}; + 15 -> {16} [style=dotted]; + 16 -> {17} [style=dotted]; 17 -> {18}; 18 -> {19}; + 19 -> {20}; + 20 -> {21}; - subgraph cluster_5 { + subgraph cluster_6 { color=red - 20 [label="Enter function foo" style="filled" fillcolor=red]; - subgraph cluster_6 { + 30 [label="Enter function foo" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 21 [label="Enter block"]; - subgraph cluster_7 { + 31 [label="Enter block"]; + subgraph cluster_8 { color=blue - 22 [label="Enter when"]; - subgraph cluster_8 { - color=blue - 23 [label="Enter when branch condition "]; - 24 [label="Const: Boolean(true)"]; - 25 [label="Exit when branch condition"]; - } - subgraph cluster_9 { - color=blue - 26 [label="Enter when branch condition else"]; - 27 [label="Exit when branch condition"]; - } - 28 [label="Enter when branch result"]; + 32 [label="Enter block"]; + 33 [label="Exit block"]; + } + subgraph cluster_9 { + color=blue + 34 [label="Enter when"]; subgraph cluster_10 { color=blue - 29 [label="Enter block"]; - subgraph cluster_11 { + 35 [label="Enter when branch condition "]; + 36 [label="Const: Boolean(true)"]; + 37 [label="Exit when branch condition"]; + } + subgraph cluster_11 { + color=blue + 38 [label="Enter when branch condition else"]; + 39 [label="Exit when branch condition"]; + } + 40 [label="Enter when branch result"]; + subgraph cluster_12 { + color=blue + 41 [label="Enter block"]; + subgraph cluster_13 { color=blue - 30 [label="Enter when"]; - subgraph cluster_12 { - color=blue - 31 [label="Enter when branch condition "]; - 32 [label="Const: Boolean(false)"]; - 33 [label="Exit when branch condition"]; - } - subgraph cluster_13 { - color=blue - 34 [label="Enter when branch condition else"]; - 35 [label="Exit when branch condition"]; - } - 36 [label="Enter when branch result"]; + 42 [label="Enter when"]; subgraph cluster_14 { color=blue - 37 [label="Enter block"]; - 38 [label="Access variable R|/y|"]; - 39 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 40 [label="Access variable R|/z|"]; - 41 [label="Function call: R|/z|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 42 [label="Jump: ^foo Unit"]; - 43 [label="Stub" style="filled" fillcolor=gray]; - 44 [label="Exit block" style="filled" fillcolor=gray]; + 43 [label="Enter when branch condition "]; + 44 [label="Const: Boolean(false)"]; + 45 [label="Exit when branch condition"]; } - 45 [label="Exit when branch result" style="filled" fillcolor=gray]; - 46 [label="Enter when branch result"]; subgraph cluster_15 { color=blue - 47 [label="Enter block"]; - 48 [label="Access variable R|/y|"]; - 49 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 50 [label="Exit block"]; + 46 [label="Enter when branch condition else"]; + 47 [label="Exit when branch condition"]; } - 51 [label="Exit when branch result"]; - 52 [label="Exit when"]; - } - 53 [label="Exit block"]; - } - 54 [label="Exit when branch result"]; - 55 [label="Enter when branch result"]; - subgraph cluster_16 { - color=blue - 56 [label="Enter block"]; - subgraph cluster_17 { - color=blue - 57 [label="Enter block"]; - 58 [label="Const: Int(0)"]; - 59 [label="Const: Int(0)"]; - 60 [label="Function call: Int(0).R|kotlin/Int.rangeTo|(...)" style="filled" fillcolor=yellow]; - 61 [label="Function call: Int(0).R|kotlin/Int.rangeTo|(...).R|kotlin/ranges/IntProgression.iterator|()" style="filled" fillcolor=yellow]; - 62 [label="Variable declaration: lval : R|kotlin/collections/IntIterator|"]; - subgraph cluster_18 { + 48 [label="Enter when branch result"]; + subgraph cluster_16 { color=blue - 63 [label="Enter while loop"]; - subgraph cluster_19 { - color=blue - 64 [label="Enter loop condition"]; - 65 [label="Access variable R|/|"]; - 66 [label="Function call: R|/|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 67 [label="Exit loop condition"]; - } - subgraph cluster_20 { - color=blue - 68 [label="Enter loop block"]; - subgraph cluster_21 { - color=blue - 69 [label="Enter block"]; - 70 [label="Access variable R|/|"]; - 71 [label="Function call: R|/|.R|kotlin/collections/IntIterator.next|()" style="filled" fillcolor=yellow]; - 72 [label="Variable declaration: lval i: R|kotlin/Int|"]; - 73 [label="Access variable R|/x|"]; - 74 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 75 [label="Exit block"]; - } - 76 [label="Exit loop block"]; - } - 77 [label="Exit whileloop"]; + 49 [label="Enter block"]; + 50 [label="Access variable R|/y|"]; + 51 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 52 [label="Access variable R|/z|"]; + 53 [label="Function call: R|/z|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 54 [label="Jump: ^foo Unit"]; + 55 [label="Stub" style="filled" fillcolor=gray]; + 56 [label="Exit block" style="filled" fillcolor=gray]; } - 78 [label="Exit block"]; + 57 [label="Exit when branch result" style="filled" fillcolor=gray]; + 58 [label="Enter when branch result"]; + subgraph cluster_17 { + color=blue + 59 [label="Enter block"]; + 60 [label="Access variable R|/y|"]; + 61 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 62 [label="Exit block"]; + } + 63 [label="Exit when branch result"]; + 64 [label="Exit when"]; } - 79 [label="Access variable R|/y|"]; - 80 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 81 [label="Exit block"]; + 65 [label="Exit block"]; } - 82 [label="Exit when branch result"]; - 83 [label="Exit when"]; - } - subgraph cluster_22 { - color=blue - 84 [label="Enter do-while loop"]; - subgraph cluster_23 { + 66 [label="Exit when branch result"]; + 67 [label="Enter when branch result"]; + subgraph cluster_18 { color=blue - 85 [label="Enter loop block"]; - subgraph cluster_24 { + 68 [label="Enter block"]; + subgraph cluster_19 { color=blue - 86 [label="Enter block"]; - 87 [label="Access variable R|/z|"]; - 88 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 89 [label="Exit block"]; + 69 [label="Enter block"]; + 70 [label="Const: Int(0)"]; + 71 [label="Const: Int(0)"]; + 72 [label="Function call: Int(0).R|kotlin/Int.rangeTo|(...)" style="filled" fillcolor=yellow]; + 73 [label="Function call: Int(0).R|kotlin/Int.rangeTo|(...).R|kotlin/ranges/IntProgression.iterator|()" style="filled" fillcolor=yellow]; + 74 [label="Variable declaration: lval : R|kotlin/collections/IntIterator|"]; + subgraph cluster_20 { + color=blue + 75 [label="Enter while loop"]; + subgraph cluster_21 { + color=blue + 76 [label="Enter loop condition"]; + 77 [label="Access variable R|/|"]; + 78 [label="Function call: R|/|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 79 [label="Exit loop condition"]; + } + subgraph cluster_22 { + color=blue + 80 [label="Enter loop block"]; + subgraph cluster_23 { + color=blue + 81 [label="Enter block"]; + 82 [label="Access variable R|/|"]; + 83 [label="Function call: R|/|.R|kotlin/collections/IntIterator.next|()" style="filled" fillcolor=yellow]; + 84 [label="Variable declaration: lval i: R|kotlin/Int|"]; + 85 [label="Access variable R|/x|"]; + 86 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 87 [label="Exit block"]; + } + 88 [label="Exit loop block"]; + } + 89 [label="Exit whileloop"]; + } + 90 [label="Exit block"]; } - 90 [label="Exit loop block"]; + 91 [label="Access variable R|/y|"]; + 92 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 93 [label="Exit block"]; } + 94 [label="Exit when branch result"]; + 95 [label="Exit when"]; + } + subgraph cluster_24 { + color=blue + 96 [label="Enter do-while loop"]; subgraph cluster_25 { color=blue - 91 [label="Enter loop condition"]; - 92 [label="Const: Boolean(true)"]; - 93 [label="Exit loop condition"]; + 97 [label="Enter loop block"]; + subgraph cluster_26 { + color=blue + 98 [label="Enter block"]; + 99 [label="Access variable R|/z|"]; + 100 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 101 [label="Exit block"]; + } + 102 [label="Exit loop block"]; } - 94 [label="Exit do-whileloop" style="filled" fillcolor=gray]; + subgraph cluster_27 { + color=blue + 103 [label="Enter loop condition"]; + 104 [label="Const: Boolean(true)"]; + 105 [label="Exit loop condition"]; + } + 106 [label="Exit do-whileloop" style="filled" fillcolor=gray]; } - 95 [label="Exit block" style="filled" fillcolor=gray]; + 107 [label="Exit block" style="filled" fillcolor=gray]; } - 96 [label="Exit function foo" style="filled" fillcolor=red]; + 108 [label="Exit function foo" style="filled" fillcolor=red]; } - 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {55 26}; - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {30}; 30 -> {31}; 31 -> {32}; 32 -> {33}; - 33 -> {46 34}; + 33 -> {34}; 34 -> {35}; 35 -> {36}; 36 -> {37}; - 37 -> {38}; + 37 -> {67 38}; 38 -> {39}; 39 -> {40}; 40 -> {41}; 41 -> {42}; - 42 -> {96}; - 42 -> {43} [style=dotted]; - 43 -> {44} [style=dotted]; - 44 -> {45} [style=dotted]; - 45 -> {52} [style=dotted]; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {58 46}; 46 -> {47}; 47 -> {48}; 48 -> {49}; @@ -234,10 +235,11 @@ digraph flow_kt { 51 -> {52}; 52 -> {53}; 53 -> {54}; - 54 -> {83}; - 55 -> {56}; - 56 -> {57}; - 57 -> {58}; + 54 -> {108}; + 54 -> {55} [style=dotted]; + 55 -> {56} [style=dotted]; + 56 -> {57} [style=dotted]; + 57 -> {64} [style=dotted]; 58 -> {59}; 59 -> {60}; 60 -> {61}; @@ -246,8 +248,8 @@ digraph flow_kt { 63 -> {64}; 64 -> {65}; 65 -> {66}; - 66 -> {67}; - 67 -> {77 68}; + 66 -> {95}; + 67 -> {68}; 68 -> {69}; 69 -> {70}; 70 -> {71}; @@ -256,10 +258,10 @@ digraph flow_kt { 73 -> {74}; 74 -> {75}; 75 -> {76}; - 76 -> {64} [color=green style=dashed]; + 76 -> {77}; 77 -> {78}; 78 -> {79}; - 79 -> {80}; + 79 -> {89 80}; 80 -> {81}; 81 -> {82}; 82 -> {83}; @@ -268,14 +270,26 @@ digraph flow_kt { 85 -> {86}; 86 -> {87}; 87 -> {88}; - 88 -> {89}; + 88 -> {76} [color=green style=dashed]; 89 -> {90}; 90 -> {91}; 91 -> {92}; 92 -> {93}; - 93 -> {94} [style=dotted]; - 93 -> {85} [color=green style=dashed]; - 94 -> {95} [style=dotted]; - 95 -> {96} [style=dotted]; + 93 -> {94}; + 94 -> {95}; + 95 -> {96}; + 96 -> {97}; + 97 -> {98}; + 98 -> {99}; + 99 -> {100}; + 100 -> {101}; + 101 -> {102}; + 102 -> {103}; + 103 -> {104}; + 104 -> {105}; + 105 -> {106} [style=dotted]; + 105 -> {97} [color=green style=dashed]; + 106 -> {107} [style=dotted]; + 107 -> {108} [style=dotted]; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.fir.txt index cf3c83109ad..2f2951e0b03 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.fir.txt @@ -1,11 +1,17 @@ FILE: flow.kt - @R|kotlin/contracts/ExperimentalContracts|() public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + when () { Boolean(true) -> { R|/x|.R|SubstitutionOverride|() @@ -15,7 +21,7 @@ FILE: flow.kt R|/bar|(R|/x|) } - @R|kotlin/contracts/ExperimentalContracts|() public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|, z: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|, z: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, UNKNOWN) @@ -23,7 +29,15 @@ FILE: flow.kt CallsInPlace(z, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.UNKNOWN|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/y|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/z|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + when () { Boolean(true) -> { { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.kt index e3e09278077..40d88929528 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/flow.kt @@ -1,7 +1,7 @@ // !DUMP_CFG import kotlin.contracts.* -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun bar(x: () -> Unit) { contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) @@ -15,7 +15,7 @@ fun bar(x: () -> Unit) { bar(x) } -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun foo(x: () -> Unit, y: () -> Unit, z: () -> Unit) { contract { callsInPlace(x, InvocationKind.UNKNOWN) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.dot index 0791b29eebf..04a4c1e1062 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.dot @@ -11,80 +11,94 @@ digraph inPlaceLambda_kt { 1 [label="Enter block"]; subgraph cluster_2 { color=blue - 2 [label="Enter when"]; - subgraph cluster_3 { - color=blue - 3 [label="Enter when branch condition "]; - 4 [label="Const: Boolean(true)"]; - 5 [label="Exit when branch condition"]; - } - 6 [label="Synthetic else branch"]; - 7 [label="Enter when branch result"]; + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + subgraph cluster_3 { + color=blue + 4 [label="Enter when"]; subgraph cluster_4 { color=blue - 8 [label="Enter block"]; - 9 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 10 [label="Exit block"]; + 5 [label="Enter when branch condition "]; + 6 [label="Const: Boolean(true)"]; + 7 [label="Exit when branch condition"]; } - 11 [label="Exit when branch result"]; - 12 [label="Exit when"]; + 8 [label="Synthetic else branch"]; + 9 [label="Enter when branch result"]; + subgraph cluster_5 { + color=blue + 10 [label="Enter block"]; + 11 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 12 [label="Exit block"]; + } + 13 [label="Exit when branch result"]; + 14 [label="Exit when"]; } - 13 [label="Exit block"]; + 15 [label="Exit block"]; } - 14 [label="Exit function bar" style="filled" fillcolor=red]; + 16 [label="Exit function bar" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; 4 -> {5}; - 5 -> {7 6}; - 6 -> {12}; - 7 -> {8}; - 8 -> {9}; + 5 -> {6}; + 6 -> {7}; + 7 -> {9 8}; + 8 -> {14}; 9 -> {10}; 10 -> {11}; 11 -> {12}; 12 -> {13}; 13 -> {14}; - - subgraph cluster_5 { - color=red - 15 [label="Enter function foo" style="filled" fillcolor=red]; - subgraph cluster_6 { - color=blue - 16 [label="Enter block"]; - 17 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 18 [label="Postponed enter to lambda"]; - subgraph cluster_7 { - color=blue - 23 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_8 { - color=blue - 24 [label="Enter block"]; - 25 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 26 [label="Exit block"]; - } - 27 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 19 [label="Postponed exit from lambda"]; - 20 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 21 [label="Exit block"]; - } - 22 [label="Exit function foo" style="filled" fillcolor=red]; - } + 14 -> {15}; 15 -> {16}; - 16 -> {17}; - 17 -> {18}; - 18 -> {19 23 20}; - 18 -> {23} [style=dashed]; - 19 -> {20}; - 20 -> {21}; - 21 -> {22}; - 23 -> {24}; - 24 -> {25}; + + subgraph cluster_6 { + color=red + 25 [label="Enter function foo" style="filled" fillcolor=red]; + subgraph cluster_7 { + color=blue + 26 [label="Enter block"]; + subgraph cluster_8 { + color=blue + 27 [label="Enter block"]; + 28 [label="Exit block"]; + } + 29 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 30 [label="Postponed enter to lambda"]; + subgraph cluster_9 { + color=blue + 35 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_10 { + color=blue + 36 [label="Enter block"]; + 37 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 38 [label="Exit block"]; + } + 39 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 31 [label="Postponed exit from lambda"]; + 32 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 33 [label="Exit block"]; + } + 34 [label="Exit function foo" style="filled" fillcolor=red]; + } 25 -> {26}; 26 -> {27}; - 27 -> {19}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {31 35 32}; + 30 -> {35} [style=dashed]; + 31 -> {32}; + 32 -> {33}; + 33 -> {34}; + 35 -> {36}; + 36 -> {37}; + 37 -> {38}; + 38 -> {39}; + 39 -> {31}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.fir.txt index 1373e7b34d5..61d94632b65 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.fir.txt @@ -1,11 +1,17 @@ FILE: inPlaceLambda.kt - @R|kotlin/contracts/ExperimentalContracts|() public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, AT_MOST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + } + ) + } + when () { Boolean(true) -> { R|/x|.R|SubstitutionOverride|() @@ -13,13 +19,19 @@ FILE: inPlaceLambda.kt } } - @R|kotlin/contracts/ExperimentalContracts|() public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, AT_LEAST_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_LEAST_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() R|/bar|( = bar@fun (): R|kotlin/Unit| { R|/x|.R|SubstitutionOverride|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.kt index 76070c5730c..0f24d8a5d49 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/inPlaceLambda.kt @@ -1,7 +1,7 @@ // !DUMP_CFG import kotlin.contracts.* -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun bar(x: () -> Unit) { contract { callsInPlace(x, InvocationKind.AT_MOST_ONCE) @@ -12,7 +12,7 @@ fun bar(x: () -> Unit) { } } -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun foo(x: () -> Unit) { contract { callsInPlace(x, InvocationKind.AT_LEAST_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.dot index d9f0a811539..cea9048843c 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.dot @@ -9,62 +9,64 @@ digraph simple_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Access variable R|/x|"]; - 3 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 4 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Access variable R|/x|"]; + 5 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 6 [label="Exit block"]; } - 5 [label="Exit function bar" style="filled" fillcolor=red]; + 7 [label="Exit function bar" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; 4 -> {5}; - - subgraph cluster_2 { - color=red - 6 [label="Enter function foo" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 7 [label="Enter block"]; - 8 [label="Access variable R|/x|"]; - 9 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - subgraph cluster_4 { - color=blue - 10 [label="Enter when"]; - subgraph cluster_5 { - color=blue - 11 [label="Enter when branch condition "]; - 12 [label="Const: Boolean(true)"]; - 13 [label="Exit when branch condition"]; - } - 14 [label="Synthetic else branch"]; - 15 [label="Enter when branch result"]; - subgraph cluster_6 { - color=blue - 16 [label="Enter block"]; - 17 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; - } - 19 [label="Exit when branch result"]; - 20 [label="Exit when"]; - } - 21 [label="Access variable R|/z|"]; - 22 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; - 23 [label="Exit block"]; - } - 24 [label="Exit function foo" style="filled" fillcolor=red]; - } + 5 -> {6}; 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - 9 -> {10}; - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {15 14}; - 14 -> {20}; - 15 -> {16}; + + subgraph cluster_3 { + color=red + 16 [label="Enter function foo" style="filled" fillcolor=red]; + subgraph cluster_4 { + color=blue + 17 [label="Enter block"]; + subgraph cluster_5 { + color=blue + 18 [label="Enter block"]; + 19 [label="Exit block"]; + } + 20 [label="Access variable R|/x|"]; + 21 [label="Function call: R|/x|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + subgraph cluster_6 { + color=blue + 22 [label="Enter when"]; + subgraph cluster_7 { + color=blue + 23 [label="Enter when branch condition "]; + 24 [label="Const: Boolean(true)"]; + 25 [label="Exit when branch condition"]; + } + 26 [label="Synthetic else branch"]; + 27 [label="Enter when branch result"]; + subgraph cluster_8 { + color=blue + 28 [label="Enter block"]; + 29 [label="Function call: R|/y|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 30 [label="Exit block"]; + } + 31 [label="Exit when branch result"]; + 32 [label="Exit when"]; + } + 33 [label="Access variable R|/z|"]; + 34 [label="Function call: R|/bar|(...)" style="filled" fillcolor=yellow]; + 35 [label="Exit block"]; + } + 36 [label="Exit function foo" style="filled" fillcolor=red]; + } 16 -> {17}; 17 -> {18}; 18 -> {19}; @@ -73,5 +75,17 @@ digraph simple_kt { 21 -> {22}; 22 -> {23}; 23 -> {24}; + 24 -> {25}; + 25 -> {27 26}; + 26 -> {32}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {31}; + 31 -> {32}; + 32 -> {33}; + 33 -> {34}; + 34 -> {35}; + 35 -> {36}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.fir.txt index 684edfb566b..d822572db0b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.fir.txt @@ -1,14 +1,20 @@ FILE: simple.kt - @R|kotlin/contracts/ExperimentalContracts|() public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun bar(x: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() } - @R|kotlin/contracts/ExperimentalContracts|() public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|, z: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun foo(x: R|() -> kotlin/Unit|, y: R|() -> kotlin/Unit|, z: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(x, EXACTLY_ONCE) @@ -16,7 +22,15 @@ FILE: simple.kt CallsInPlace(z, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/x|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/y|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.AT_MOST_ONCE|) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/z|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + R|/x|.R|SubstitutionOverride|() when () { Boolean(true) -> { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.kt index 8ef28dcb9d7..ed7cb7eb411 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/simple.kt @@ -1,7 +1,7 @@ // !DUMP_CFG import kotlin.contracts.* -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun bar(x: () -> Unit) { contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) @@ -10,7 +10,7 @@ fun bar(x: () -> Unit) { x.invoke() } -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) fun foo(x: () -> Unit, y: () -> Unit, z: () -> Unit) { contract { callsInPlace(x, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot index c9640539e94..9149dfe846d 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.dot @@ -9,122 +9,136 @@ digraph unknown_kt { subgraph cluster_1 { color=blue 1 [label="Enter block"]; - 2 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 3 [label="Exit block"]; + subgraph cluster_2 { + color=blue + 2 [label="Enter block"]; + 3 [label="Exit block"]; + } + 4 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 5 [label="Exit block"]; } - 4 [label="Exit function inlineRun" style="filled" fillcolor=red]; + 6 [label="Exit function inlineRun" style="filled" fillcolor=red]; } 0 -> {1}; 1 -> {2}; 2 -> {3}; 3 -> {4}; - - subgraph cluster_2 { - color=red - 5 [label="Enter function myRun" style="filled" fillcolor=red]; - subgraph cluster_3 { - color=blue - 6 [label="Enter block"]; - 7 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; - 8 [label="Exit block"]; - } - 9 [label="Exit function myRun" style="filled" fillcolor=red]; - } + 4 -> {5}; 5 -> {6}; - 6 -> {7}; - 7 -> {8}; - 8 -> {9}; - subgraph cluster_4 { + subgraph cluster_3 { color=red - 10 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_5 { + 15 [label="Enter function myRun" style="filled" fillcolor=red]; + subgraph cluster_4 { color=blue - 11 [label="Enter block"]; - 12 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 13 [label="Postponed enter to lambda"]; - subgraph cluster_6 { + 16 [label="Enter block"]; + subgraph cluster_5 { color=blue - 20 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_7 { - color=blue - 21 [label="Enter block"]; - 22 [label="Const: Int(1)"]; - 23 [label="Assignment: R|/x|"]; - 24 [label="Exit block"]; - } - 25 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 17 [label="Enter block"]; + 18 [label="Exit block"]; } - 14 [label="Postponed exit from lambda"]; - 15 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; - 16 [label="Access variable R|/x|"]; - 17 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 18 [label="Exit block"]; + 19 [label="Function call: R|/block|.R|SubstitutionOverride|()" style="filled" fillcolor=yellow]; + 20 [label="Exit block"]; } - 19 [label="Exit function test_1" style="filled" fillcolor=red]; + 21 [label="Exit function myRun" style="filled" fillcolor=red]; } - 10 -> {11}; - 11 -> {12}; - 12 -> {13}; - 13 -> {14 20 15}; - 13 -> {20} [style=dashed]; - 14 -> {15}; - 14 -> {13} [color=green style=dashed]; 15 -> {16}; 16 -> {17}; 17 -> {18}; 18 -> {19}; + 19 -> {20}; 20 -> {21}; - 21 -> {22}; - 22 -> {23}; - 23 -> {24}; - 24 -> {25}; - 25 -> {14}; - subgraph cluster_8 { + subgraph cluster_6 { color=red - 26 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_9 { + 30 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_7 { color=blue - 27 [label="Enter block"]; - 28 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 29 [label="Postponed enter to lambda"]; - subgraph cluster_10 { + 31 [label="Enter block"]; + 32 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 33 [label="Postponed enter to lambda"]; + subgraph cluster_8 { color=blue - 36 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_11 { + 40 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 37 [label="Enter block"]; - 38 [label="Const: Int(1)"]; - 39 [label="Assignment: R|/x|"]; - 40 [label="Exit block"]; + 41 [label="Enter block"]; + 42 [label="Const: Int(1)"]; + 43 [label="Assignment: R|/x|"]; + 44 [label="Exit block"]; } - 41 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 45 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 30 [label="Postponed exit from lambda"]; - 31 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; - 32 [label="Access variable R|/x|"]; - 33 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; - 34 [label="Exit block"]; + 34 [label="Postponed exit from lambda"]; + 35 [label="Function call: R|/inlineRun|(...)" style="filled" fillcolor=yellow]; + 36 [label="Access variable R|/x|"]; + 37 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 38 [label="Exit block"]; } - 35 [label="Exit function test_2" style="filled" fillcolor=red]; + 39 [label="Exit function test_1" style="filled" fillcolor=red]; } - 26 -> {27}; - 27 -> {28}; - 28 -> {29}; - 29 -> {30 36 31}; - 29 -> {36} [style=dashed]; 30 -> {31}; - 30 -> {29} [color=green style=dashed]; 31 -> {32}; 32 -> {33}; - 33 -> {34}; + 33 -> {34 40 35}; + 33 -> {40} [style=dashed]; 34 -> {35}; + 34 -> {33} [color=green style=dashed]; + 35 -> {36}; 36 -> {37}; 37 -> {38}; 38 -> {39}; - 39 -> {40}; 40 -> {41}; - 41 -> {30}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; + 44 -> {45}; + 45 -> {34}; + + subgraph cluster_10 { + color=red + 46 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_11 { + color=blue + 47 [label="Enter block"]; + 48 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 49 [label="Postponed enter to lambda"]; + subgraph cluster_12 { + color=blue + 56 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + subgraph cluster_13 { + color=blue + 57 [label="Enter block"]; + 58 [label="Const: Int(1)"]; + 59 [label="Assignment: R|/x|"]; + 60 [label="Exit block"]; + } + 61 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + } + 50 [label="Postponed exit from lambda"]; + 51 [label="Function call: R|/myRun|(...)" style="filled" fillcolor=yellow]; + 52 [label="Access variable R|/x|"]; + 53 [label="Function call: R|/x|.R|kotlin/Int.inc|()" style="filled" fillcolor=yellow]; + 54 [label="Exit block"]; + } + 55 [label="Exit function test_2" style="filled" fillcolor=red]; + } + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50 56 51}; + 49 -> {56} [style=dashed]; + 50 -> {51}; + 50 -> {49} [color=green style=dashed]; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {61}; + 61 -> {50}; } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.fir.txt index 0c68b9a376c..ec436c73254 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.fir.txt @@ -1,20 +1,32 @@ FILE: unknown.kt - public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, UNKNOWN) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.UNKNOWN|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } - public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] < CallsInPlace(block, UNKNOWN) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.UNKNOWN|) + } + ) + } + R|/block|.R|SubstitutionOverride|() } public final fun test_1(): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.kt index 4a6ed0eb69d..ff269919ca9 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/unknown.kt @@ -2,6 +2,7 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) inline fun inlineRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.UNKNOWN) @@ -9,6 +10,7 @@ inline fun inlineRun(block: () -> Unit) { block() } +@OptIn(ExperimentalContracts::class) fun myRun(block: () -> Unit) { contract { callsInPlace(block, InvocationKind.UNKNOWN) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.fir.txt index 8074e930c43..0e1a684a267 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.fir.txt @@ -1,11 +1,17 @@ FILE: booleanOperators.kt - public final fun myRequire(b: R|kotlin/Boolean|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRequire(b: R|kotlin/Boolean|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> b > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(R|/b|) + } + ) + } + when () { R|/b|.R|kotlin/Boolean.not|() -> { throw R|java/lang/IllegalStateException.IllegalStateException|() @@ -13,13 +19,19 @@ FILE: booleanOperators.kt } } - public final fun myRequireAnd(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRequireAnd(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> b1 && b2 > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(R|/b1| && R|/b2|) + } + ) + } + when () { R|/b1| && R|/b2|.R|kotlin/Boolean.not|() -> { throw R|java/lang/IllegalStateException.IllegalStateException|() @@ -27,13 +39,19 @@ FILE: booleanOperators.kt } } - public final fun myRequireOr(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRequireOr(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> b1 || b2 > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(R|/b1| || R|/b2|) + } + ) + } + when () { R|/b1| || R|/b2|.R|kotlin/Boolean.not|() -> { throw R|java/lang/IllegalStateException.IllegalStateException|() @@ -41,13 +59,19 @@ FILE: booleanOperators.kt } } - public final fun myRequireNot(b: R|kotlin/Boolean|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun myRequireNot(b: R|kotlin/Boolean|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> !b > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(R|/b|.R|kotlin/Boolean.not|()) + } + ) + } + when () { R|/b| -> { throw R|java/lang/IllegalStateException.IllegalStateException|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.kt index e310196c7fe..8d3e212f2fd 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/booleanOperators.kt @@ -1,5 +1,6 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) fun myRequire(b: Boolean) { contract { returns() implies (b) @@ -7,6 +8,7 @@ fun myRequire(b: Boolean) { if (!b) throw IllegalStateException() } +@OptIn(ExperimentalContracts::class) fun myRequireAnd(b1: Boolean, b2: Boolean) { contract { returns() implies (b1 && b2) @@ -14,6 +16,7 @@ fun myRequireAnd(b1: Boolean, b2: Boolean) { if (!(b1 && b2)) throw IllegalStateException() } +@OptIn(ExperimentalContracts::class) fun myRequireOr(b1: Boolean, b2: Boolean) { contract { returns() implies (b1 || b2) @@ -21,6 +24,7 @@ fun myRequireOr(b1: Boolean, b2: Boolean) { if (!(b1 || b2)) throw IllegalStateException() } +@OptIn(ExperimentalContracts::class) fun myRequireNot(b: Boolean) { contract { returns() implies (!b) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.fir.txt index 4213b9b0bb9..97706e2992e 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.fir.txt @@ -5,25 +5,43 @@ FILE: conditionLogic.kt Returns(NOT_NULL) -> !x == null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(==(R|/x|, Null(null)).R|kotlin/Boolean.not|()) + } + ) + } + ^test1 R|/x| } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test2(x: R|kotlin/String?|): R|kotlin/Any?| [R|Contract description] < - Returns(NOT_NULL) -> x is kotlin/String && x != null + Returns(NOT_NULL) -> x is kotlin/String > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|)) + } + ) + } + ^test2 R|/x| } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test3(x: R|kotlin/String?|): R|kotlin/Any?| [R|Contract description] < - Returns(NOT_NULL) -> x is kotlin/String? || x is kotlin/Any? + Returns(NOT_NULL) -> x !is kotlin/String > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| !is R|kotlin/String|)) + } + ) + } + ^test3 R|/x| } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test4(x: R|kotlin/String?|, y: R|kotlin/String?|): R|kotlin/Any?| @@ -32,7 +50,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x != null && y != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null)) && !=(R|/y|, Null(null))) + } + ) + } + ^test4 !=(R|/x|, Null(null)) && !=(R|/y|, Null(null)) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test5(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -41,7 +65,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x != null || x is kotlin/Any > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null)) || (R|/x| is R|kotlin/Any|)) + } + ) + } + ^test5 !=(R|/x|, Null(null)) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test6(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -50,7 +80,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/String? && x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String?|) && !=(R|/x|, Null(null))) + } + ) + } + ^test6 (R|/x| is R|kotlin/String|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test7(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -59,7 +95,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/String? && x != null || x is kotlin/Int > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String?|) && !=(R|/x|, Null(null)) || (R|/x| is R|kotlin/Int|)) + } + ) + } + ^test7 (R|/x| is R|kotlin/String|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test8(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -68,7 +110,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/String || x is kotlin/Int > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|) || (R|/x| is R|kotlin/Int|)) + } + ) + } + ^test8 (R|/x| is R|kotlin/String|) || (R|/x| is R|kotlin/Int|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test9(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -77,7 +125,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/String || x is kotlin/Int > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|) || (R|/x| is R|kotlin/Int|)) + } + ) + } + when () { (R|/x| is R|kotlin/String|) -> { ^test9 Boolean(true) @@ -92,7 +146,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/Comparable<*> || x is kotlin/CharSequence > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/Comparable<*>|) || (R|/x| is R|kotlin/CharSequence|)) + } + ) + } + ^test10 (R|/x| is R|kotlin/String|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test11(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -101,7 +161,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/Comparable<*> && x is kotlin/CharSequence > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/Comparable<*>|) && (R|/x| is R|kotlin/CharSequence|)) + } + ) + } + ^test11 (R|/x| is R|kotlin/String|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test12(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -110,7 +176,13 @@ FILE: conditionLogic.kt Returns(TRUE) -> x is kotlin/Comparable<*> && x is kotlin/CharSequence || x is kotlin/Number > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/Comparable<*>|) && (R|/x| is R|kotlin/CharSequence|) || (R|/x| is R|kotlin/Number|)) + } + ) + } + ^test12 (R|/x| is R|kotlin/String|) || (R|/x| is R|kotlin/Int|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test13(x: R|kotlin/Any?|): R|kotlin/Any?| @@ -119,6 +191,12 @@ FILE: conditionLogic.kt Returns(TRUE) -> (!)x !is kotlin/Comparable<*> || x !is kotlin/CharSequence && (!x is kotlin/Number) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| !is R|kotlin/Comparable<*>|) || (R|/x| !is R|kotlin/CharSequence|) && (R|/x| is R|kotlin/Number|).R|kotlin/Boolean.not|().R|kotlin/Boolean.not|()) + } + ) + } + ^test13 (R|/x| is R|kotlin/String|) || (R|/x| is R|kotlin/Int|) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.kt index 0da8a8c70b6..4bc82525550 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/conditionLogic.kt @@ -13,7 +13,7 @@ fun test1(x: String?): Any? { @OptIn(ExperimentalContracts::class) fun test2(x: String?): Any? { contract { - returnsNotNull() implies (x is String && x != null) + returnsNotNull() implies (x is String) } return x @@ -22,7 +22,7 @@ fun test2(x: String?): Any? { @OptIn(ExperimentalContracts::class) fun test3(x: String?): Any? { contract { - returnsNotNull() implies (x is String? || x is Any?) + returnsNotNull() implies (x !is String) } return x diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.fir.txt index 10057c52f4c..132401f1bdb 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.fir.txt @@ -1,21 +1,34 @@ FILE: eqNotEq.kt - public final fun checkNotNull(x: R|kotlin/Any?|): R|kotlin/Boolean| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun checkNotNull(x: R|kotlin/Any?|): R|kotlin/Boolean| [R|Contract description] < Returns(TRUE) -> x != null Returns(FALSE) -> x == null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(false)).R|kotlin/contracts/SimpleEffect.implies|(==(R|/x|, Null(null))) + } + ) + } + ^checkNotNull !=(R|/x|, Null(null)) } - public final fun trickyRequireNotNull(x: R|kotlin/Any?|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun trickyRequireNotNull(x: R|kotlin/Any?|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> !x == null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(==(R|/x|, Null(null)).R|kotlin/Boolean.not|()) + } + ) + } + when () { ==(R|/x|, Null(null)) -> { throw R|java/lang/IllegalStateException.IllegalStateException|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt index f9af2c7d18d..f7e7bd2d086 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/eqNotEq.kt @@ -1,5 +1,6 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) fun checkNotNull(x: Any?): Boolean { contract { returns(true) implies (x != null) @@ -8,6 +9,7 @@ fun checkNotNull(x: Any?): Boolean { return x != null } +@OptIn(ExperimentalContracts::class) fun trickyRequireNotNull(x: Any?) { contract { returns() implies (!(x == null)) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/inapplicable.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/inapplicable.fir.txt index 492bd71cef3..98ae880c5f3 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/inapplicable.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/inapplicable.fir.txt @@ -5,7 +5,13 @@ FILE: inapplicable.kt Returns(FALSE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(false)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^wrongFalse Boolean(true) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun wrongTrue(x: R|kotlin/String?|): R|kotlin/Boolean| @@ -14,7 +20,13 @@ FILE: inapplicable.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^wrongTrue Boolean(false) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun nullableConstant(x: R|kotlin/String?|): R|kotlin/Any?| @@ -23,7 +35,13 @@ FILE: inapplicable.kt Returns(NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Null(null)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^nullableConstant Int(1) } public final fun string(): R|kotlin/String| { @@ -35,7 +53,13 @@ FILE: inapplicable.kt Returns(NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Null(null)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^nullableReturn R|/string|() } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun returnsNull(x: R|kotlin/String?|): R|kotlin/Any?| @@ -44,7 +68,13 @@ FILE: inapplicable.kt Returns(NOT_NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^returnsNull Null(null) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun wrongReturnType(x: R|kotlin/String?|): R|kotlin/Any?| @@ -53,6 +83,12 @@ FILE: inapplicable.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^wrongReturnType String(true) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt index e5acdd0b7e9..eddc3a95d16 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt @@ -1,11 +1,17 @@ FILE: namedArguments.kt - public final fun foo(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun foo(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> x is kotlin/Int && y is kotlin/String > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/Int|) && (R|/y| is R|kotlin/String|)) + } + ) + } + when () { (R|/x| !is R|kotlin/Int|) || (R|/y| !is R|kotlin/String|) -> { throw R|java/lang/IllegalStateException.IllegalStateException|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt index 4166e0598d9..ec147487db9 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.kt @@ -1,5 +1,6 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) fun foo(x: Any, y: Any) { contract { returns() implies (x is Int && y is String) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/notNull.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/notNull.fir.txt index 396be52c438..3ba816cc9e9 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/notNull.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/notNull.fir.txt @@ -5,7 +5,13 @@ FILE: notNull.kt Returns(FALSE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(false)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test1 ==(R|/x|, Null(null)) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test2(x: R|kotlin/String?|): R|kotlin/Boolean| @@ -14,7 +20,13 @@ FILE: notNull.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test2 !=(R|/x|, Null(null)) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test3(x: R|kotlin/String?|): R|kotlin/Any?| @@ -23,7 +35,13 @@ FILE: notNull.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + when () { !=(R|/x|, Null(null)) -> { ^test3 Boolean(true) @@ -38,7 +56,13 @@ FILE: notNull.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + lval y: R|kotlin/String?| = R|/x| when () { !=(R|/y|, Null(null)) -> { @@ -54,6 +78,12 @@ FILE: notNull.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test5 R|/test2|(R|/x|) } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.fir.txt index d9a89954ce6..586cf25fa91 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.fir.txt @@ -3,14 +3,20 @@ FILE: propertyAccessors.kt public abstract fun foo(): R|kotlin/Unit| } - public final var R|kotlin/Any?|.isNotNull: R|kotlin/Boolean| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final var R|kotlin/Any?|.isNotNull: R|kotlin/Boolean| public get(): R|kotlin/Boolean| [R|Contract description] < Returns(TRUE) -> this != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(this@R|/isNotNull|, Null(null))) + } + ) + } + ^ !=(this@R|/isNotNull|, Null(null)) } public set(value: R|kotlin/Boolean|): R|kotlin/Unit| @@ -19,7 +25,14 @@ FILE: propertyAccessors.kt Returns(WILDCARD) -> this != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(!=(this@R|/isNotNull|, Null(null))) + R|kotlin/require|(!=(this@R|special/anonymous|, Null(null))) + } + ) + } + } public final fun test_1(a: R|A?|): R|kotlin/Unit| { when () { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.kt index 7f7e3ea88fd..4b18197ce28 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/propertyAccessors.kt @@ -4,6 +4,7 @@ interface A { fun foo() } +@OptIn(ExperimentalContracts::class) var Any?.isNotNull: Boolean get() { contract { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.fir.txt index 81e985f3d35..3d47c5dc075 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.fir.txt @@ -3,13 +3,19 @@ FILE: receivers.kt } public final fun R|A|.foo(): R|kotlin/Unit| { } - public final fun R|kotlin/Any?|.myRequireNotNull(): R|kotlin/Unit| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun R|kotlin/Any?|.myRequireNotNull(): R|kotlin/Unit| [R|Contract description] < Returns(WILDCARD) -> this != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|().R|kotlin/contracts/SimpleEffect.implies|(!=(this@R|/myRequireNotNull|, Null(null))) + } + ) + } + when () { ==(this@R|/myRequireNotNull|, Null(null)) -> { throw R|java/lang/IllegalStateException.IllegalStateException|() diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.kt index 6087af3a99d..6f030511119 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/receivers.kt @@ -4,6 +4,7 @@ interface A fun A.foo() {} +@OptIn(ExperimentalContracts::class) fun Any?.myRequireNotNull() { contract { returns() implies (this@myRequireNotNull != null) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/safeCall.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/safeCall.fir.txt index 325ff1c3df4..592557acf15 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/safeCall.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/safeCall.fir.txt @@ -5,7 +5,13 @@ FILE: safeCall.kt Returns(NOT_NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test1 R|/x|?.{ $subj$.R|kotlin/String.length| } } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test2(x: R|kotlin/String?|): R|kotlin/Int?| @@ -14,6 +20,12 @@ FILE: safeCall.kt Returns(NOT_NULL) -> x is kotlin/Boolean > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/Boolean|)) + } + ) + } + ^test2 R|/x|?.{ $subj$.R|kotlin/String.length| } } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/trickyCases.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/trickyCases.fir.txt index 5c3224eccce..e8e4b3a7615 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/trickyCases.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/trickyCases.fir.txt @@ -5,7 +5,13 @@ FILE: trickyCases.kt Returns(NOT_NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test1 R|/x| } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun test2(x: R|kotlin/String?|): R|kotlin/Any?| @@ -14,7 +20,13 @@ FILE: trickyCases.kt Returns(TRUE) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test2 when () { !=(R|/x|, Null(null)) -> { Boolean(true) @@ -31,7 +43,13 @@ FILE: trickyCases.kt Returns(NOT_NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test3 when () { Boolean(true) -> { R|/x| @@ -48,7 +66,13 @@ FILE: trickyCases.kt Returns(NOT_NULL) -> x != null > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returnsNotNull|().R|kotlin/contracts/SimpleEffect.implies|(!=(R|/x|, Null(null))) + } + ) + } + ^test4 when () { !=(R|/x|, Null(null)) -> { when () { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.fir.txt index 938fde1e804..15fdff8d706 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.fir.txt @@ -1,12 +1,19 @@ FILE: typePredicate.kt - public final fun checkIsString(x: R|kotlin/Any|): R|kotlin/Boolean| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun checkIsString(x: R|kotlin/Any|): R|kotlin/Boolean| [R|Contract description] < Returns(TRUE) -> x is kotlin/String Returns(FALSE) -> x !is kotlin/String > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(true)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| is R|kotlin/String|)) + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.returns|(Boolean(false)).R|kotlin/contracts/SimpleEffect.implies|((R|/x| !is R|kotlin/String|)) + } + ) + } + ^checkIsString (R|/x| is R|kotlin/String|) } public final fun test(x: R|kotlin/Any|): R|kotlin/Unit| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt index 5c222089784..1c4589672d0 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/typePredicate.kt @@ -1,5 +1,6 @@ import kotlin.contracts.* +@OptIn(ExperimentalContracts::class) fun checkIsString(x: Any): Boolean { contract { returns(true) implies (x is String) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.fir.txt index 56bb47cc6f3..80fe57bba59 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.fir.txt @@ -12,13 +12,19 @@ FILE: annotationArgumentMapping.kt } } - public final fun buildAnnotationArgumentMapping(init: R|FirAnnotationArgumentMappingBuilder.() -> kotlin/Unit|): R|FirAnnotationArgumentMapping| + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final fun buildAnnotationArgumentMapping(init: R|FirAnnotationArgumentMappingBuilder.() -> kotlin/Unit|): R|FirAnnotationArgumentMapping| [R|Contract description] < CallsInPlace(init, EXACTLY_ONCE) > { - [StubStatement] + { + R|kotlin/contracts/contract|( = contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/init|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + ^buildAnnotationArgumentMapping R|/FirAnnotationArgumentMappingBuilder.FirAnnotationArgumentMappingBuilder|().R|kotlin/apply|(R|/init|).R|/FirAnnotationArgumentMappingBuilder.build|() } public final class FirAnnotationArgumentMapping : R|kotlin/Any| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.kt index 0c10fe34d08..feea3065e0b 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/annotationArgumentMapping.kt @@ -8,6 +8,7 @@ class FirAnnotationArgumentMappingBuilder { } } +@OptIn(ExperimentalContracts::class) fun buildAnnotationArgumentMapping(init: FirAnnotationArgumentMappingBuilder.() -> Unit): FirAnnotationArgumentMapping { contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 5d4fa2ae3fc..57a65a4fd8a 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -5193,6 +5193,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("noOptIn.kt") + public void testNoOptIn() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace") @TestDataPath("$PROJECT_ROOT") @@ -5247,6 +5253,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { public void testPropertyGetter() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.kt"); } + + @Test + @TestMetadata("redundantConditions.kt") + public void testRedundantConditions() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt"); + } } } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 41412576eb9..80e20af45dc 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -5193,6 +5193,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("noOptIn.kt") + public void testNoOptIn() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/noOptIn.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/callsInPlace") @TestDataPath("$PROJECT_ROOT") @@ -5247,6 +5253,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos public void testPropertyGetter() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/propertyGetter.kt"); } + + @Test + @TestMetadata("redundantConditions.kt") + public void testRedundantConditions() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/redundantConditions.kt"); + } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt index 6ebad6f8224..83f6f30d92c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt @@ -34,6 +34,7 @@ abstract class CheckerContext : MutableDiagnosticContext() { abstract val qualifiedAccessOrAnnotationCalls: List abstract val getClassCalls: List abstract val annotationContainers: List + abstract val isContractBody: Boolean // Suppress abstract val suppressedDiagnostics: Set @@ -71,6 +72,10 @@ abstract class CheckerContext : MutableDiagnosticContext() { abstract fun dropAnnotationContainer() + abstract fun enterContractBody(): CheckerContext + + abstract fun exitContractBody(): CheckerContext + override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean { val factory = diagnostic.factory val name = factory.name diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt index dbd4410a8e6..058072d09d9 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt @@ -23,6 +23,7 @@ class MutableCheckerContext private constructor( override val qualifiedAccessOrAnnotationCalls: MutableList, override val getClassCalls: MutableList, override val annotationContainers: MutableList, + override var isContractBody: Boolean, sessionHolder: SessionHolder, returnTypeCalculator: ReturnTypeCalculator, override val suppressedDiagnostics: PersistentSet, @@ -36,6 +37,7 @@ class MutableCheckerContext private constructor( mutableListOf(), mutableListOf(), mutableListOf(), + isContractBody = false, sessionHolder, returnTypeCalculator, persistentSetOf(), @@ -51,6 +53,7 @@ class MutableCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -109,6 +112,7 @@ class MutableCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics.addAll(diagnosticNames), @@ -117,4 +121,16 @@ class MutableCheckerContext private constructor( this.allErrorsSuppressed || allErrorsSuppressed ) } + + override fun enterContractBody(): CheckerContext { + check(!isContractBody) + isContractBody = true + return this + } + + override fun exitContractBody(): CheckerContext { + check(isContractBody) + isContractBody = false + return this + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt index d85ffbab186..733f6af83ff 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt @@ -25,6 +25,7 @@ class PersistentCheckerContext private constructor( override val qualifiedAccessOrAnnotationCalls: PersistentList, override val getClassCalls: PersistentList, override val annotationContainers: PersistentList, + override val isContractBody: Boolean, sessionHolder: SessionHolder, returnTypeCalculator: ReturnTypeCalculator, override val suppressedDiagnostics: PersistentSet, @@ -38,6 +39,7 @@ class PersistentCheckerContext private constructor( persistentListOf(), persistentListOf(), persistentListOf(), + isContractBody = false, sessionHolder, returnTypeCalculator, persistentSetOf(), @@ -53,6 +55,7 @@ class PersistentCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -69,6 +72,7 @@ class PersistentCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -88,6 +92,7 @@ class PersistentCheckerContext private constructor( this.qualifiedAccessOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall), getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -107,6 +112,7 @@ class PersistentCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls.add(getClassCall), annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -126,6 +132,7 @@ class PersistentCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers.add(annotationContainer), + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics, @@ -151,6 +158,7 @@ class PersistentCheckerContext private constructor( qualifiedAccessOrAnnotationCalls, getClassCalls, annotationContainers, + isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics.addAll(diagnosticNames), @@ -159,4 +167,31 @@ class PersistentCheckerContext private constructor( this.allErrorsSuppressed || allErrorsSuppressed ) } + + private fun toggleContractBody(newValue: Boolean): CheckerContext { + check(isContractBody != newValue) + + return PersistentCheckerContext( + implicitReceiverStack, + containingDeclarations, + qualifiedAccessOrAnnotationCalls, + getClassCalls, + annotationContainers, + isContractBody = newValue, + sessionHolder, + returnTypeCalculator, + suppressedDiagnostics, + allInfosSuppressed, + allWarningsSuppressed, + allErrorsSuppressed + ) + } + + override fun enterContractBody(): CheckerContext { + return toggleContractBody(newValue = true) + } + + override fun exitContractBody(): CheckerContext { + return toggleContractBody(newValue = false) + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContractChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContractChecker.kt index cf73de5bf8e..423776b4a50 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContractChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirContractChecker.kt @@ -26,7 +26,8 @@ object FirContractChecker : FirFunctionChecker() { } // Any statements that [ConeEffectExtractor] cannot extract effects will be in `unresolvedEffects`. - for (statement in (declaration.contractDescription as FirResolvedContractDescription).unresolvedEffects) { + for (unresolvedEffect in (declaration.contractDescription as FirResolvedContractDescription).unresolvedEffects) { + val statement = unresolvedEffect.statement if (statement.source == null || statement.source!!.kind is KtFakeSourceElementKind) continue // TODO: report on fine-grained locations, e.g., ... implies unresolved => report on unresolved, not the entire statement. diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index abc1151f191..3eaa333cd57 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -131,6 +131,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() { targetSymbol: FirBasedSymbol<*>?, context: CheckerContext ) { + if (context.isContractBody) return val calledFunctionSymbol = targetSymbol as? FirNamedFunctionSymbol ?: return val argumentMapping = functionCall.resolvedArgumentMapping ?: return for ((wrappedArgument, valueParameter) in argumentMapping) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt index 2456e002029..477357c261f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt @@ -42,7 +42,7 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker() { reporter.reportOn(expression.source, FirErrors.UNCHECKED_CAST, actualType, targetType, context) } } else if (expression.operation == FirOperation.IS) { - if (isCastErased(actualType, targetType, context)) { + if (!context.isContractBody && isCastErased(actualType, targetType, context)) { reporter.reportOn(conversionTypeRef.source, FirErrors.CANNOT_CHECK_FOR_ERASED, targetType, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt index 4922c823d51..8a34d6fedd8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -166,7 +167,13 @@ abstract class AbstractDiagnosticCollectorVisitor( override fun visitBlock(block: FirBlock, data: Nothing?) { withAnnotationContainer(block) { - visitExpression(block, data) + if (block is FirContractCallBlock) { + insideContractBody { + visitExpression(block, data) + } + } else { + visitExpression(block, data) + } } } @@ -352,6 +359,16 @@ abstract class AbstractDiagnosticCollectorVisitor( } } + @OptIn(PrivateForInline::class) + private inline fun insideContractBody(block: () -> R): R { + context = context.enterContractBody() + return try { + block() + } finally { + context = context.exitContractBody() + } + } + private inline fun withTypeRefAnnotationContainer(annotationContainer: FirTypeRef, block: () -> R): R { var containingTypeRef = context.annotationContainers.lastOrNull() as? FirResolvedTypeRef while (containingTypeRef != null && containingTypeRef.delegatedTypeRef != annotationContainer) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 3033d8edbe8..ead41b279a8 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isSealed import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression @@ -660,6 +661,7 @@ class Fir2IrVisitor( if (this is FirTypeAlias) return null if (this == FirStubStatement) return null if (this is FirUnitExpression) return convertToIrExpression(this) + if (this is FirContractCallBlock) return null if (this is FirBlock) return convertToIrExpression(this) return accept(this@Fir2IrVisitor, null) as IrStatement } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 7d5fddd0cda..95a5a9444b9 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -1030,7 +1030,7 @@ class DeclarationsConverter( annotations += modifiers.annotations typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters) valueParameters += firValueParameters.map { it.firValueParameter } - val (body, _) = convertFunctionBody(block, null) + val (body, _) = convertFunctionBody(block, null, allowLegacyContractDescription = true) this.body = body context.firFunctionTargets.removeLast() }.also { @@ -1460,9 +1460,8 @@ class DeclarationsConverter( if (!isGetter) { valueParameters += firValueParameters } - - val hasContractEffectList = outerContractDescription != null - val bodyWithContractDescription = convertFunctionBody(block, expression, hasContractEffectList) + val allowLegacyContractDescription = outerContractDescription == null + val bodyWithContractDescription = convertFunctionBody(block, expression, allowLegacyContractDescription) this.body = bodyWithContractDescription.first val contractDescription = outerContractDescription ?: bodyWithContractDescription.second contractDescription?.let { @@ -1720,8 +1719,8 @@ class DeclarationsConverter( ).map { it.firValueParameter } } - val hasContractEffectList = outerContractDescription != null - val bodyWithContractDescription = convertFunctionBody(block, expression, hasContractEffectList) + val allowLegacyContractDescription = outerContractDescription == null && !isLocal + val bodyWithContractDescription = convertFunctionBody(block, expression, allowLegacyContractDescription) this.body = bodyWithContractDescription.first val contractDescription = outerContractDescription ?: bodyWithContractDescription.second contractDescription?.let { @@ -1755,16 +1754,13 @@ class DeclarationsConverter( private fun convertFunctionBody( blockNode: LighterASTNode?, expression: LighterASTNode?, - hasContractEffectList: Boolean = false + allowLegacyContractDescription: Boolean ): Pair { return when { blockNode != null -> { val block = convertBlock(blockNode) - if (hasContractEffectList) { - block to null - } else { - block.extractContractDescriptionIfPossible() - } + val contractDescription = runIf(allowLegacyContractDescription) { processLegacyContractDescription(block) } + block to contractDescription } expression != null -> FirSingleExpressionBlock( expressionConverter.getAsFirExpression(expression, "Function has no body (but should)").toReturn() diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 046669ac088..2df355d7151 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -363,16 +363,16 @@ open class RawFirBuilder( } } - private fun KtDeclarationWithBody.buildFirBody(): Pair = + private fun KtDeclarationWithBody.buildFirBody(allowLegacyContractDescription: Boolean): Pair = if (hasBody()) { buildOrLazyBlock { if (hasBlockBody()) { val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock - return@buildFirBody if (hasContractEffectList()) { - block to null - } else { - block.extractContractDescriptionIfPossible() + val contractDescription = when { + allowLegacyContractDescription && !hasContractEffectList() -> block?.let(::processLegacyContractDescription) + else -> null } + return@buildFirBody block to contractDescription } else { val result = { bodyExpression }.toFirExpression("Function has no body (but should)") FirSingleExpressionBlock(result.toReturn(baseSource = result.source)) @@ -469,7 +469,7 @@ open class RawFirBuilder( } } val outerContractDescription = this@toFirPropertyAccessor.obtainContractDescription() - val bodyWithContractDescription = this@toFirPropertyAccessor.buildFirBody() + val bodyWithContractDescription = this@toFirPropertyAccessor.buildFirBody(allowLegacyContractDescription = true) this.body = bodyWithContractDescription.first val contractDescription = outerContractDescription ?: bodyWithContractDescription.second contractDescription?.let { @@ -1417,6 +1417,7 @@ open class RawFirBuilder( val labelName: String? val isAnonymousFunction = function.isAnonymous + val isLocalFunction = function.isLocal val functionSymbol: FirFunctionSymbol<*> val functionBuilder = if (isAnonymousFunction) { FirAnonymousFunctionBuilder().apply { @@ -1435,7 +1436,7 @@ open class RawFirBuilder( symbol = FirNamedFunctionSymbol(callableIdForName(function.nameAsSafeName)).also { functionSymbol = it } dispatchReceiverType = currentDispatchReceiverType() status = FirDeclarationStatusImpl( - if (function.isLocal) Visibilities.Local else function.visibility, + if (isLocalFunction) Visibilities.Local else function.visibility, function.modality, ).apply { isExpect = function.hasExpectModifier() || context.containerIsExpect @@ -1480,7 +1481,7 @@ open class RawFirBuilder( listOf() withCapturedTypeParameters(true, functionSource, actualTypeParameters) { val outerContractDescription = function.obtainContractDescription() - val bodyWithContractDescription = function.buildFirBody() + val bodyWithContractDescription = function.buildFirBody(!isLocalFunction) this.body = bodyWithContractDescription.first val contractDescription = outerContractDescription ?: bodyWithContractDescription.second contractDescription?.let { @@ -1653,7 +1654,7 @@ open class RawFirBuilder( extractValueParametersTo(this, symbol, ValueParameterDeclaration.FUNCTION) - val (body, _) = buildFirBody() + val (body, _) = buildFirBody(allowLegacyContractDescription = true) this.body = body this@RawFirBuilder.context.firFunctionTargets.removeLast() }.also { diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contracts/oldSyntax/contractDescription.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contracts/oldSyntax/contractDescription.txt index f843f89bbb8..6a5077b5c94 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contracts/oldSyntax/contractDescription.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contracts/oldSyntax/contractDescription.txt @@ -7,7 +7,13 @@ FILE: contractDescription.kt ) > { - [StubStatement] + { + contract#( = contract@fun .(): { + callsInPlace#() + } + ) + } + test_1#() } public? final? fun test_2(): R|kotlin/Unit| @@ -19,7 +25,14 @@ FILE: contractDescription.kt ) > { - [StubStatement] + { + kotlin#.contracts#.contract#( = contract@fun .(): { + callsInPlace#() + callsInPlace#() + } + ) + } + test_2#() } public? final? var test_3: Int = IntegerLiteral(1) @@ -31,7 +44,13 @@ FILE: contractDescription.kt ) > { - [StubStatement] + { + contract#( = contract@fun .(): { + callsInPlace#() + } + ) + } + ^ IntegerLiteral(1) } public? set(value: Int): R|kotlin/Unit| @@ -43,14 +62,24 @@ FILE: contractDescription.kt ) > { - [StubStatement] + { + kotlin#.contracts#.contract#( = contract@fun .(): { + callsInPlace#() + callsInPlace#() + } + ) + } + } public? final? fun test_4(): R|kotlin/Unit| [Contract description] < contract#() > { - [StubStatement] + { + contract#() + } + test_4#() } public? final? fun test_5(): R|kotlin/Unit| { diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt index 92ecf6fc57c..d67f009a166 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt @@ -13,12 +13,14 @@ import com.intellij.util.PathUtil import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirFunctionTypeParameter +import org.jetbrains.kotlin.fir.contracts.FirContractDescription import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement import org.jetbrains.kotlin.fir.references.impl.FirStubReference @@ -182,12 +184,13 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase( } } -private fun throwTwiceVisitingError(element: FirElement, @Suppress("UNUSED_PARAMETER") parent: FirElement?) { +private fun throwTwiceVisitingError(element: FirElement, parent: FirElement?) { if (element is FirTypeRef || element is FirNoReceiverExpression || element is FirTypeParameter || element is FirTypeProjection || element is FirValueParameter || element is FirAnnotation || element is FirFunctionTypeParameter || element is FirEmptyContractDescription || element is FirStubReference || element.isExtensionFunctionAnnotation || element is FirEmptyArgumentList || - element is FirStubStatement || element === FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS + element is FirStubStatement || element === FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS || + ((parent is FirContractCallBlock || parent is FirContractDescription) && element is FirFunctionCall) ) { return } diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 3f653084e89..752255e157b 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -26,8 +26,8 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* +import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock -import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.builder.buildDelegateFieldReference import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference @@ -496,14 +496,16 @@ fun FirPropertyBuilder.generateAccessorsByDelegate( } } -fun FirBlock?.extractContractDescriptionIfPossible(): Pair { - if (this == null) return null to null - if (!isContractPresentFirCheck()) return this to null - val contractCall = replaceFirstStatement(FirStubStatement) as FirFunctionCall - return this to buildLegacyRawContractDescription { - source = contractCall.source - this.contractCall = contractCall +fun processLegacyContractDescription(block: FirBlock): FirContractDescription? { + if (block.isContractPresentFirCheck()) { + val contractCall = block.replaceFirstStatement { FirContractCallBlock(it) } + return buildLegacyRawContractDescription { + source = contractCall.source + this.contractCall = contractCall + } } + + return null } fun FirBlock.isContractPresentFirCheck(): Boolean { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt index 0c1a195cb43..c72b7a4aa4c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration +import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration import org.jetbrains.kotlin.fir.declarations.* @@ -20,6 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.errorTypeFromPrototype import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* +import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.ResolutionMode @@ -128,35 +130,53 @@ abstract class FirAbstractContractResolveTransformerDispatcher( } } - private fun transformContractDescriptionOwner( - owner: T - ): T { + private fun transformContractDescriptionOwner(owner: T): T { dataFlowAnalyzer.enterContractDescription() + return when (val contractDescription = owner.contractDescription) { - is FirLegacyRawContractDescription -> transformLegacyRawContractDescriptionOwner(owner, contractDescription) - is FirRawContractDescription -> transformRawContractDescriptionOwner(owner, contractDescription) - else -> throw IllegalArgumentException("$owner has a contract description of an unknown type") + is FirLegacyRawContractDescription -> + transformLegacyRawContractDescriptionOwner(owner, contractDescription, hasBodyContract = true) + is FirRawContractDescription -> + transformRawContractDescriptionOwner(owner, contractDescription) + else -> + throw IllegalArgumentException("$owner has a contract description of an unknown type") } } private fun transformLegacyRawContractDescriptionOwner( owner: T, - contractDescription: FirLegacyRawContractDescription + contractDescription: FirLegacyRawContractDescription, + hasBodyContract: Boolean ): T { val valueParameters = owner.valueParameters for (valueParameter in valueParameters) { context.storeVariable(valueParameter, session) } - val contractCall = try { - contractMode = false - contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent) - } finally { - contractMode = true + + val resolvedContractCall = withContractModeDisabled { + contractDescription.contractCall + .transformSingle(transformer, ResolutionMode.ContextIndependent) + .apply { replaceTypeRef(session.builtinTypes.unitType) } } - val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner) - if (resolvedId != FirContractsDslNames.CONTRACT) return transformOwnerWithUnresolvedContract(owner) - if (contractCall.arguments.size != 1) return transformOwnerOfErrorContract(owner) - val argument = contractCall.argument as? FirLambdaArgumentExpression ?: return transformOwnerOfErrorContract(owner) + + if (resolvedContractCall.toResolvedCallableSymbol()?.callableId != FirContractsDslNames.CONTRACT) { + if (hasBodyContract) { + owner.body.replaceFirstStatement { resolvedContractCall } + } + owner.replaceContractDescription(FirEmptyContractDescription) + dataFlowAnalyzer.exitContractDescription() + return owner + } + + if (hasBodyContract) { + // Until the contract description is replaced with a resolved one, a call rests both in the description + // and in the callable body (scoped inside a marker block). Here we patch the second call occurrence. + owner.body.replaceFirstStatement { FirContractCallBlock(resolvedContractCall) } + } + + val argument = resolvedContractCall.arguments.singleOrNull() as? FirLambdaArgumentExpression + ?: return transformOwnerOfErrorContract(owner) + val lambdaBody = (argument.expression as FirAnonymousFunctionExpression).anonymousFunction.body ?: return transformOwnerOfErrorContract(owner) @@ -165,18 +185,27 @@ abstract class FirAbstractContractResolveTransformerDispatcher( for (statement in lambdaBody.statements) { val effect = statement.accept(effectExtractor, null) as? ConeEffectDeclaration if (effect == null) { - unresolvedEffects += statement + unresolvedEffects += ConeUnresolvedEffect(statement) } else { effects += effect.toFirEffectDeclaration(statement.source) } } - this.source = owner.contractDescription.source + this.source = contractDescription.source } owner.replaceContractDescription(resolvedContractDescription) dataFlowAnalyzer.exitContractDescription() return owner } + private inline fun withContractModeDisabled(block: () -> T): T { + try { + contractMode = false + return block() + } finally { + contractMode = true + } + } + private fun transformRawContractDescriptionOwner( owner: T, contractDescription: FirRawContractDescription @@ -220,25 +249,7 @@ abstract class FirAbstractContractResolveTransformerDispatcher( owner.replaceContractDescription(legacyRawContractDescription) - return transformLegacyRawContractDescriptionOwner(owner, legacyRawContractDescription) - } - - private fun transformOwnerWithUnresolvedContract(owner: T): T { - return when (val contractDescription = owner.contractDescription) { - is FirLegacyRawContractDescription -> { // old syntax contract description - val functionCall = contractDescription.contractCall - owner.replaceContractDescription(FirEmptyContractDescription) - owner.body.replaceFirstStatement(functionCall) - dataFlowAnalyzer.exitContractDescription() - owner - } - is FirRawContractDescription -> { // new syntax contract description - owner.replaceContractDescription(FirEmptyContractDescription) - dataFlowAnalyzer.exitContractDescription() - owner - } - else -> owner // TODO: change - } + return transformLegacyRawContractDescriptionOwner(owner, legacyRawContractDescription, hasBodyContract = false) } open fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/FirResolvedContractDescription.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/FirResolvedContractDescription.kt index 4f226f65cc9..1cb9c9c805f 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/FirResolvedContractDescription.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/FirResolvedContractDescription.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.contracts import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect import org.jetbrains.kotlin.fir.visitors.* /* @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.visitors.* abstract class FirResolvedContractDescription : FirContractDescription() { abstract override val source: KtSourceElement? abstract val effects: List - abstract val unresolvedEffects: List + abstract val unresolvedEffects: List override fun accept(visitor: FirVisitor, data: D): R = visitor.visitResolvedContractDescription(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/builder/FirResolvedContractDescriptionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/builder/FirResolvedContractDescriptionBuilder.kt index 1a861eceebc..74819da08f6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/builder/FirResolvedContractDescriptionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/builder/FirResolvedContractDescriptionBuilder.kt @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription +import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect import org.jetbrains.kotlin.fir.contracts.impl.FirResolvedContractDescriptionImpl -import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.visitors.* /* @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.fir.visitors.* class FirResolvedContractDescriptionBuilder { var source: KtSourceElement? = null val effects: MutableList = mutableListOf() - val unresolvedEffects: MutableList = mutableListOf() + val unresolvedEffects: MutableList = mutableListOf() fun build(): FirResolvedContractDescription { return FirResolvedContractDescriptionImpl( diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/impl/FirResolvedContractDescriptionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/impl/FirResolvedContractDescriptionImpl.kt index d5ba90d9070..749f32591c3 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/impl/FirResolvedContractDescriptionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/contracts/impl/FirResolvedContractDescriptionImpl.kt @@ -10,7 +10,7 @@ package org.jetbrains.kotlin.fir.contracts.impl import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription -import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect import org.jetbrains.kotlin.fir.visitors.* /* @@ -21,16 +21,14 @@ import org.jetbrains.kotlin.fir.visitors.* internal class FirResolvedContractDescriptionImpl( override val source: KtSourceElement?, override val effects: MutableList, - override val unresolvedEffects: MutableList, + override val unresolvedEffects: MutableList, ) : FirResolvedContractDescription() { override fun acceptChildren(visitor: FirVisitor, data: D) { effects.forEach { it.accept(visitor, data) } - unresolvedEffects.forEach { it.accept(visitor, data) } } override fun transformChildren(transformer: FirTransformer, data: D): FirResolvedContractDescriptionImpl { effects.transformInplace(transformer, data) - unresolvedEffects.transformInplace(transformer, data) return this } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeUnresolvedEffect.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeUnresolvedEffect.kt new file mode 100644 index 00000000000..14a037a0d2e --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeUnresolvedEffect.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.contracts.description + +import org.jetbrains.kotlin.fir.expressions.FirStatement + +class ConeUnresolvedEffect(val statement: FirStatement) \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt index aeed960e0e3..2be0e5751dc 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt @@ -104,13 +104,14 @@ fun FirBlock.transformStatementsIndexed(transformer: FirTransformer, data return this } -fun FirBlock.replaceFirstStatement(statement: FirStatement): FirStatement { +fun FirBlock.replaceFirstStatement(factory: (T) -> FirStatement): T { require(this is FirBlockImpl) { "replaceFirstStatement should not be called for ${this::class.simpleName}" } - val existed = statements[0] - statements[0] = statement - return existed + @Suppress("UNCHECKED_CAST") + val existing = statements[0] as T + statements[0] = factory(existing) + return existing } fun FirExpression.unwrapArgument(): FirExpression = (this as? FirWrappedArgumentExpression)?.expression ?: this diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirContractCallBlock.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirContractCallBlock.kt new file mode 100644 index 00000000000..bf65a31705b --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirContractCallBlock.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions.impl + +import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fakeElement +import org.jetbrains.kotlin.fir.MutableOrEmptyList +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.FirVisitor +import org.jetbrains.kotlin.fir.visitors.transformInplace +import org.jetbrains.kotlin.fir.visitors.transformSingle + +class FirContractCallBlock(var call: FirFunctionCall) : FirBlock() { + override val source: KtSourceElement? + get() = call.source?.fakeElement(KtFakeSourceElementKind.ContractBlock) + + override val statements: List + get() = listOf(call) + + override var annotations: MutableOrEmptyList = MutableOrEmptyList.empty() + override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) + + override fun acceptChildren(visitor: FirVisitor, data: D) { + call.accept(visitor, data) + typeRef.accept(visitor, data) + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirContractCallBlock { + transformStatements(transformer, data) + transformOtherChildren(transformer, data) + return this + } + + override fun replaceTypeRef(newTypeRef: FirTypeRef) { + typeRef = newTypeRef + } + + override fun transformStatements(transformer: FirTransformer, data: D): FirBlock { + call = call.transformSingle(transformer, data) + return this + } + + override fun transformOtherChildren(transformer: FirTransformer, data: D): FirBlock { + typeRef = typeRef.transformSingle(transformer, data) + return this + } + + override fun replaceAnnotations(newAnnotations: List) { + annotations = newAnnotations.toMutableOrEmpty() + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirBlock { + annotations.transformInplace(transformer, data) + return this + } +} \ No newline at end of file diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 2db36bb1610..da30eb1e38d 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -726,7 +726,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild resolvedContractDescription.configure { +fieldList("effects", effectDeclaration) - +fieldList("unresolvedEffects", statement) + +fieldList("unresolvedEffects", coneUnresolvedEffect) } legacyRawContractDescription.configure { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt index dfd205c3076..7e948e4658f 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt @@ -80,6 +80,7 @@ val coneEffectDeclarationType = type("fir.contracts.description", "ConeEffectDec val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription") val coneDiagnosticType = generatedType("diagnostics", "ConeDiagnostic") val coneStubDiagnosticType = generatedType("diagnostics", "ConeStubDiagnostic") +val coneUnresolvedEffect = type("fir.contracts.description", "ConeUnresolvedEffect") val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl") val firImplementationDetailType = generatedType("FirImplementationDetail") diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt index dff05ff6a63..3f41b0c3b4a 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt @@ -113,6 +113,9 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // with a fake sources for the block which refers to the wrapped expression object SingleExpressionBlock : KtFakeSourceElementKind() + // Contract statements are wrapped in a special block to be reused between a contract FIR and a function body. + object ContractBlock : KtFakeSourceElementKind() + // x++ -> x = x.inc() // x = x++ -> x = { val = x; x = .inc(); } object DesugaredIncrementOrDecrement : KtFakeSourceElementKind() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt index a10f815e71a..fcd1f08e00b 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt @@ -156,29 +156,29 @@ fun T?.case_22_3(): Boolean? { // TESTCASE NUMBER: 23 fun T.case_23_1(): Boolean { - contract { returns(false) implies (this@case_23_1 !is Int || this@case_23_1 == null) } + contract { returns(false) implies (this@case_23_1 !is Int || this@case_23_1 == null) } return !(this@case_23_1 !is Int || this@case_23_1 == null) } fun T.case_23_2(): Boolean? { - contract { returnsNotNull() implies (this@case_23_2 !is Int || this@case_23_2 == null) } + contract { returnsNotNull() implies (this@case_23_2 !is Int || this@case_23_2 == null) } return if (this@case_23_2 !is Int || this@case_23_2 == null) true else null } fun T.case_23_3(): Boolean? { - contract { returns(null) implies (this@case_23_3 !is Int || this@case_23_3 == null) } + contract { returns(null) implies (this@case_23_3 !is Int || this@case_23_3 == null) } return if (this@case_23_3 !is Int || this@case_23_3 == null) null else true } // TESTCASE NUMBER: 24 inline fun T?.case_24_1(): Boolean { - contract { returns(false) implies (this@case_24_1 !is Number || this@case_24_1 !is Int || this@case_24_1 == null) } + contract { returns(false) implies (this@case_24_1 !is Number || this@case_24_1 !is Int || this@case_24_1 == null) } return !(this@case_24_1 !is Number || this@case_24_1 !is Int || this@case_24_1 == null) } inline fun T?.case_24_2(): Boolean? { - contract { returnsNotNull() implies (this@case_24_2 !is Number || this@case_24_2 !is Int || this@case_24_2 == null) } + contract { returnsNotNull() implies (this@case_24_2 !is Number || this@case_24_2 !is Int || this@case_24_2 == null) } return if (this@case_24_2 !is Number || this@case_24_2 !is Int || this@case_24_2 == null) true else null } inline fun T?.case_24_3(): Boolean? { - contract { returns(null) implies (this@case_24_3 !is Number || this@case_24_3 !is Int || this@case_24_3 == null) } + contract { returns(null) implies (this@case_24_3 !is Number || this@case_24_3 !is Int || this@case_24_3 == null) } return if (this@case_24_3 !is Number || this@case_24_3 !is Int || this@case_24_3 == null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt index 85a1076ce67..2b022f8c1c4 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt @@ -14,13 +14,13 @@ fun T?.case_1() { // TESTCASE NUMBER: 2 fun T.case_2() { - contract { returns() implies (this@case_2 !is Int || this@case_2 == null) } + contract { returns() implies (this@case_2 !is Int || this@case_2 == null) } if (!(this@case_2 !is Int || this@case_2 == null)) throw Exception() } // TESTCASE NUMBER: 3 inline fun T?.case_3() { - contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null) } + contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null) } if (!(this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null)) throw Exception() } @@ -44,37 +44,37 @@ fun T?.case_4_4(): Boolean? { // TESTCASE NUMBER: 5 fun T.case_5_1(): Boolean { - contract { returns(true) implies (this@case_5_1 !is Int || this@case_5_1 == null) } + contract { returns(true) implies (this@case_5_1 !is Int || this@case_5_1 == null) } return this@case_5_1 !is Int || this@case_5_1 == null } fun T.case_5_2(): Boolean { - contract { returns(false) implies (this@case_5_2 !is Int || this@case_5_2 == null) } + contract { returns(false) implies (this@case_5_2 !is Int || this@case_5_2 == null) } return !(this@case_5_2 !is Int || this@case_5_2 == null) } fun T.case_5_3(): Boolean? { - contract { returnsNotNull() implies (this@case_5_3 !is Int || this@case_5_3 == null) } + contract { returnsNotNull() implies (this@case_5_3 !is Int || this@case_5_3 == null) } return if (this@case_5_3 !is Int || this@case_5_3 == null) true else null } fun T.case_5_4(): Boolean? { - contract { returns(null) implies (this@case_5_4 !is Int || this@case_5_4 == null) } + contract { returns(null) implies (this@case_5_4 !is Int || this@case_5_4 == null) } return if (this@case_5_4 !is Int || this@case_5_4 == null) null else true } // TESTCASE NUMBER: 6 inline fun T?.case_6_1(): Boolean { - contract { returns(true) implies (this@case_6_1 !is Number || this@case_6_1 !is Int || this@case_6_1 == null) } + contract { returns(true) implies (this@case_6_1 !is Number || this@case_6_1 !is Int || this@case_6_1 == null) } return this@case_6_1 !is Number || this@case_6_1 !is Int || this@case_6_1 == null } inline fun T?.case_6_2(): Boolean { - contract { returns(false) implies (this@case_6_2 !is Number || this@case_6_2 !is Int || this@case_6_2 == null) } + contract { returns(false) implies (this@case_6_2 !is Number || this@case_6_2 !is Int || this@case_6_2 == null) } return !(this@case_6_2 !is Number || this@case_6_2 !is Int || this@case_6_2 == null) } inline fun T?.case_6_3(): Boolean? { - contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } + contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } return if (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) true else null } inline fun T?.case_6_4(): Boolean? { - contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } + contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } return if (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt index 19300cdbfb2..db9e71af3a9 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt @@ -14,13 +14,13 @@ fun T?.case_1(value_1: Int?) { // TESTCASE NUMBER: 2 fun T.case_2(value_2: Any?) { - contract { returns() implies (this@case_2 !is Int || this@case_2 == null || value_2 !is Number || value_2 == null) } + contract { returns() implies (this@case_2 !is Int || this@case_2 == null || value_2 !is Number || value_2 == null) } if (!(this@case_2 !is Int || this@case_2 == null || value_2 !is Number || value_2 == null)) throw Exception() } // TESTCASE NUMBER: 3 fun T?.case_3(value_2: Any?) { - contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null || value_2 == null) } + contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null || value_2 == null) } if (!(this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null || value_2 == null)) throw Exception() } @@ -50,37 +50,37 @@ fun T?.case_5_4(value_1: Int?): Boolean? { // TESTCASE NUMBER: 6 fun T.case_6_1(value_2: Any?): Boolean { - contract { returns(true) implies (this@case_6_1 !is Int || this@case_6_1 == null || value_2 !is Number || value_2 == null) } + contract { returns(true) implies (this@case_6_1 !is Int || this@case_6_1 == null || value_2 !is Number || value_2 == null) } return this@case_6_1 !is Int || this@case_6_1 == null || value_2 !is Number || value_2 == null } fun T.case_6_2(value_2: Any?): Boolean { - contract { returns(false) implies (this@case_6_2 !is Int || this@case_6_2 == null || value_2 !is Number || value_2 == null) } + contract { returns(false) implies (this@case_6_2 !is Int || this@case_6_2 == null || value_2 !is Number || value_2 == null) } return !(this@case_6_2 !is Int || this@case_6_2 == null || value_2 !is Number || value_2 == null) } fun T.case_6_3(value_2: Any?): Boolean? { - contract { returnsNotNull() implies (this@case_6_3 !is Int || this@case_6_3 == null || value_2 !is Number || value_2 == null) } + contract { returnsNotNull() implies (this@case_6_3 !is Int || this@case_6_3 == null || value_2 !is Number || value_2 == null) } return if (this@case_6_3 !is Int || this@case_6_3 == null || value_2 !is Number || value_2 == null) true else null } fun T.case_6_4(value_2: Any?): Boolean? { - contract { returns(null) implies (this@case_6_4 !is Int || this@case_6_4 == null || value_2 !is Number || value_2 == null) } + contract { returns(null) implies (this@case_6_4 !is Int || this@case_6_4 == null || value_2 !is Number || value_2 == null) } return if (this@case_6_4 !is Int || this@case_6_4 == null || value_2 !is Number || value_2 == null) null else true } // TESTCASE NUMBER: 7 fun T?.case_7_1(value_2: Any?): Boolean { - contract { returns(true) implies (this@case_7_1 !is Number || this@case_7_1 !is Int || this@case_7_1 == null || value_2 == null) } + contract { returns(true) implies (this@case_7_1 !is Number || this@case_7_1 !is Int || this@case_7_1 == null || value_2 == null) } return this@case_7_1 !is Number || this@case_7_1 !is Int || this@case_7_1 == null || value_2 == null } fun T?.case_7_2(value_2: Any?): Boolean { - contract { returns(false) implies (this@case_7_2 !is Number || this@case_7_2 !is Int || this@case_7_2 == null || value_2 == null) } + contract { returns(false) implies (this@case_7_2 !is Number || this@case_7_2 !is Int || this@case_7_2 == null || value_2 == null) } return !(this@case_7_2 !is Number || this@case_7_2 !is Int || this@case_7_2 == null || value_2 == null) } fun T?.case_7_3(value_2: Any?): Boolean? { - contract { returnsNotNull() implies (this@case_7_3 !is Number || this@case_7_3 !is Int || this@case_7_3 == null || value_2 == null) } + contract { returnsNotNull() implies (this@case_7_3 !is Number || this@case_7_3 !is Int || this@case_7_3 == null || value_2 == null) } return if (this@case_7_3 !is Number || this@case_7_3 !is Int || this@case_7_3 == null || value_2 == null) true else null } fun T?.case_7_4(value_2: Any?): Boolean? { - contract { returns(null) implies (this@case_7_4 !is Number || this@case_7_4 !is Int || this@case_7_4 == null || value_2 == null) } + contract { returns(null) implies (this@case_7_4 !is Number || this@case_7_4 !is Int || this@case_7_4 == null || value_2 == null) } return if (this@case_7_4 !is Number || this@case_7_4 !is Int || this@case_7_4 == null || value_2 == null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt index 67004894c2f..4ea924e043e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt @@ -14,13 +14,13 @@ fun T?.case_1() { // TESTCASE NUMBER: 2 fun T.case_2() { - contract { returns() implies (this@case_2 is Int && this@case_2 != null) } + contract { returns() implies (this@case_2 is Int && this@case_2 != null) } if (!(this@case_2 is Int && this@case_2 != null)) throw Exception() } // TESTCASE NUMBER: 3 inline fun T?.case_3() { - contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null) } + contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null) } if (!(this@case_3 is Number && this@case_3 is Int && this@case_3 != null)) throw Exception() } @@ -44,37 +44,37 @@ fun T?.case_4_4(): Boolean? { // TESTCASE NUMBER: 5 fun T.case_5_1(): Boolean { - contract { returns(true) implies (this@case_5_1 is Int && this@case_5_1 != null) } + contract { returns(true) implies (this@case_5_1 is Int && this@case_5_1 != null) } return this@case_5_1 is Int && this@case_5_1 != null } fun T.case_5_2(): Boolean { - contract { returns(false) implies (this@case_5_2 is Int && this@case_5_2 != null) } + contract { returns(false) implies (this@case_5_2 is Int && this@case_5_2 != null) } return !(this@case_5_2 is Int && this@case_5_2 != null) } fun T.case_5_3(): Boolean? { - contract { returnsNotNull() implies (this@case_5_3 is Int && this@case_5_3 != null) } + contract { returnsNotNull() implies (this@case_5_3 is Int && this@case_5_3 != null) } return if (this@case_5_3 is Int && this@case_5_3 != null) true else null } fun T.case_5_4(): Boolean? { - contract { returns(null) implies (this@case_5_4 is Int && this@case_5_4 != null) } + contract { returns(null) implies (this@case_5_4 is Int && this@case_5_4 != null) } return if (this@case_5_4 is Int && this@case_5_4 != null) null else true } // TESTCASE NUMBER: 6 inline fun T?.case_6_1(): Boolean { - contract { returns(true) implies (this@case_6_1 is Number && this@case_6_1 is Int && this@case_6_1 != null) } + contract { returns(true) implies (this@case_6_1 is Number && this@case_6_1 is Int && this@case_6_1 != null) } return this@case_6_1 is Number && this@case_6_1 is Int && this@case_6_1 != null } inline fun T?.case_6_2(): Boolean { - contract { returns(false) implies (this@case_6_2 is Number && this@case_6_2 is Int && this@case_6_2 != null) } + contract { returns(false) implies (this@case_6_2 is Number && this@case_6_2 is Int && this@case_6_2 != null) } return !(this@case_6_2 is Number && this@case_6_2 is Int && this@case_6_2 != null) } inline fun T?.case_6_3(): Boolean? { - contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } + contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } return if (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) true else null } inline fun T?.case_6_4(): Boolean? { - contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } + contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } return if (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt index f4689db565e..360f055c49f 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt @@ -14,13 +14,13 @@ fun T?.case_1(value_1: Int?) { // TESTCASE NUMBER: 2 fun T.case_2(value_2: Any?) { - contract { returns() implies (this@case_2 is Int && this@case_2 != null && value_2 is Number && value_2 != null) } + contract { returns() implies (this@case_2 is Int && this@case_2 != null && value_2 is Number && value_2 != null) } if (!(this@case_2 is Int && this@case_2 != null && value_2 is Number && value_2 != null)) throw Exception() } // TESTCASE NUMBER: 3 fun T?.case_3(value_2: Any?) { - contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null && value_2 != null) } + contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null && value_2 != null) } if (!(this@case_3 is Number && this@case_3 is Int && this@case_3 != null && value_2 != null)) throw Exception() } @@ -50,37 +50,37 @@ fun T?.case_5_4(value_1: Int?): Boolean? { // TESTCASE NUMBER: 6 fun T.case_6_1(value_2: Any?): Boolean { - contract { returns(true) implies (this@case_6_1 is Int && this@case_6_1 != null && value_2 is Number && value_2 != null) } + contract { returns(true) implies (this@case_6_1 is Int && this@case_6_1 != null && value_2 is Number && value_2 != null) } return this@case_6_1 is Int && this@case_6_1 != null && value_2 is Number && value_2 != null } fun T.case_6_2(value_2: Any?): Boolean { - contract { returns(false) implies (this@case_6_2 is Int && this@case_6_2 != null && value_2 is Number && value_2 != null) } + contract { returns(false) implies (this@case_6_2 is Int && this@case_6_2 != null && value_2 is Number && value_2 != null) } return !(this@case_6_2 is Int && this@case_6_2 != null && value_2 is Number && value_2 != null) } fun T.case_6_3(value_2: Any?): Boolean? { - contract { returnsNotNull() implies (this@case_6_3 is Int && this@case_6_3 != null && value_2 is Number && value_2 != null) } + contract { returnsNotNull() implies (this@case_6_3 is Int && this@case_6_3 != null && value_2 is Number && value_2 != null) } return if (this@case_6_3 is Int && this@case_6_3 != null && value_2 is Number && value_2 != null) true else null } fun T.case_6_4(value_2: Any?): Boolean? { - contract { returns(null) implies (this@case_6_4 is Int && this@case_6_4 != null && value_2 is Number && value_2 != null) } + contract { returns(null) implies (this@case_6_4 is Int && this@case_6_4 != null && value_2 is Number && value_2 != null) } return if (this@case_6_4 is Int && this@case_6_4 != null && value_2 is Number && value_2 != null) null else true } // TESTCASE NUMBER: 7 fun T?.case_7_1(value_2: Any?): Boolean { - contract { returns(true) implies (this@case_7_1 is Number && this@case_7_1 is Int && this@case_7_1 != null && value_2 != null) } + contract { returns(true) implies (this@case_7_1 is Number && this@case_7_1 is Int && this@case_7_1 != null && value_2 != null) } return this@case_7_1 is Number && this@case_7_1 is Int && this@case_7_1 != null && value_2 != null } fun T?.case_7_2(value_2: Any?): Boolean { - contract { returns(true) implies (this@case_7_2 is Number && this@case_7_2 is Int && this@case_7_2 != null && value_2 != null) } + contract { returns(true) implies (this@case_7_2 is Number && this@case_7_2 is Int && this@case_7_2 != null && value_2 != null) } return this@case_7_2 is Number && this@case_7_2 is Int && this@case_7_2 != null && value_2 != null } fun T?.case_7_3(value_2: Any?): Boolean? { - contract { returnsNotNull() implies (this@case_7_3 is Number && this@case_7_3 is Int && this@case_7_3 != null && value_2 != null) } + contract { returnsNotNull() implies (this@case_7_3 is Number && this@case_7_3 is Int && this@case_7_3 != null && value_2 != null) } return if (this@case_7_3 is Number && this@case_7_3 is Int && this@case_7_3 != null && value_2 != null) true else null } fun T?.case_7_4(value_2: Any?): Boolean? { - contract { returns(null) implies (this@case_7_4 is Number && this@case_7_4 is Int && this@case_7_4 != null && value_2 != null) } + contract { returns(null) implies (this@case_7_4 is Number && this@case_7_4 is Int && this@case_7_4 != null && value_2 != null) } return if (this@case_7_4 is Number && this@case_7_4 is Int && this@case_7_4 != null && value_2 != null) null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt index 16f38b2194b..c2171d3bb41 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt @@ -5,7 +5,7 @@ import kotlin.contracts.* // TESTCASE NUMBER: 1 fun T.case_1() { - contract { returns() implies (this@case_1 is T) } + contract { returns() implies (this@case_1 is T) } if (!(this@case_1 is T)) throw Exception() } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt index 71e5ef321e7..e27633c4534 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt @@ -65,7 +65,7 @@ fun case_11(value_1: Any?): Boolean? { // TESTCASE NUMBER: 12 fun Char.case_12() { - contract { returns() implies (this@case_12 == null) } + contract { returns() implies (this@case_12 == null) } if (this@case_12 != null) throw Exception() } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt index ba53aa1f2d4..8ce0f5ae64d 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt @@ -43,7 +43,7 @@ class case_4 : ClassLevel3() { fun T.case_4_3_wrap() { fun case_4_3_contract() { - contract { returns() implies (this@case_4_3_wrap is ClassLevel1) } + contract { returns() implies (this@case_4_3_wrap is ClassLevel1) } if (this@case_4_3_wrap !is ClassLevel1) throw Exception() } case_4_3_contract()