diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt index a456a93c506..1e8b1b82ee5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzerImpl.kt @@ -101,11 +101,19 @@ class FirDataFlowAnalyzerImpl(transformer: FirBodyResolveTransformer) : FirDataF // ----------------------------------- Operator call ----------------------------------- + private fun FirExpression.getResolvedSymbol(): FirCallableSymbol<*>? { + val expression = (this as? FirWhenSubjectExpression)?.whenSubject?.whenExpression?.let { + it.subjectVariable?.symbol?.let { return it } + it.subject + } ?: this + return expression.toResolvedCallableSymbol() as? FirCallableSymbol<*> + } + override fun exitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall) { val node = graphBuilder.exitTypeOperatorCall(typeOperatorCall).passFlow(false) try { if (typeOperatorCall.operation !in FirOperation.TYPES) return - val symbol: FirCallableSymbol<*> = typeOperatorCall.argument.toResolvedCallableSymbol() as? FirCallableSymbol<*> ?: return + val symbol: FirCallableSymbol<*> = typeOperatorCall.argument.getResolvedSymbol() ?: return val type = typeOperatorCall.conversionTypeRef.coneTypeSafe() ?: return val varVariable = getRealVariable(symbol) diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.cfg.dot b/compiler/fir/resolve/testData/resolve/smartcasts/when.cfg.dot new file mode 100644 index 00000000000..e5c6a9d4804 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/when.cfg.dot @@ -0,0 +1,514 @@ +digraph when_kt { +subgraph foo { + 0 [shape=box label="Enter function foo"]; + 1 [shape=box label="Exit function foo"]; + + 0 -> {1}; +} + +subgraph bar { + 2 [shape=box label="Enter function bar"]; + 3 [shape=box label="Exit function bar"]; + + 2 -> {3}; +} + +subgraph test_1 { + 4 [shape=box label="Enter function test_1"]; + 5 [shape=box label="Enter block"]; + 6 [shape=box label="Enter when"]; + 7 [shape=box label="Enter when branch condition "]; + 8 [shape=box label="Access variable R|/x|"]; + 9 [shape=box label="Type operator: x is A"]; + 10 [shape=box label="Exit when branch condition"]; + 11 [shape=box label="Enter block"]; + 12 [shape=box label="Access variable R|/x|"]; + 13 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 14 [shape=box label="Exit block"]; + 15 [shape=box label="Exit when branch result"]; + 16 [shape=box label="Enter when branch condition "]; + 17 [shape=box label="Access variable R|/x|"]; + 18 [shape=box label="Type operator: x is B"]; + 19 [shape=box label="Exit when branch condition"]; + 20 [shape=box label="Enter block"]; + 21 [shape=box label="Access variable R|/x|"]; + 22 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 23 [shape=box label="Exit block"]; + 24 [shape=box label="Exit when branch result"]; + 25 [shape=box label="Enter when branch condition else"]; + 26 [shape=box label="Exit when branch condition"]; + 27 [shape=box label="Enter block"]; + 28 [shape=box label="Exit block"]; + 29 [shape=box label="Exit when branch result"]; + 30 [shape=box label="Exit when"]; + 31 [shape=box label="Enter when"]; + 32 [shape=box label="Enter when branch condition "]; + 33 [shape=box label="Access variable R|/x|"]; + 34 [shape=box label="Type operator: x !is A"]; + 35 [shape=box label="Exit when branch condition"]; + 36 [shape=box label="Enter block"]; + 37 [shape=box label="Exit block"]; + 38 [shape=box label="Exit when branch result"]; + 39 [shape=box label="Enter when branch condition "]; + 40 [shape=box label="Access variable R|/x|"]; + 41 [shape=box label="Type operator: x !is B"]; + 42 [shape=box label="Exit when branch condition"]; + 43 [shape=box label="Enter block"]; + 44 [shape=box label="Access variable R|/x|"]; + 45 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 46 [shape=box label="Exit block"]; + 47 [shape=box label="Exit when branch result"]; + 48 [shape=box label="Enter when branch condition "]; + 49 [shape=box label="Access variable R|/x|"]; + 50 [shape=box label="Type operator: x is Int"]; + 51 [shape=box label="Exit when branch condition"]; + 52 [shape=box label="Enter block"]; + 53 [shape=box label="Access variable R|/x|"]; + 54 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 55 [shape=box label="Access variable R|/x|"]; + 56 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 57 [shape=box label="Access variable R|/x|"]; + 58 [shape=box label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 59 [shape=box label="Exit block"]; + 60 [shape=box label="Exit when branch result"]; + 61 [shape=box label="Enter when branch condition else"]; + 62 [shape=box label="Exit when branch condition"]; + 63 [shape=box label="Enter block"]; + 64 [shape=box label="Access variable R|/x|"]; + 65 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 66 [shape=box label="Access variable R|/x|"]; + 67 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 68 [shape=box label="Exit block"]; + 69 [shape=box label="Exit when branch result"]; + 70 [shape=box label="Exit when"]; + 71 [shape=box label="Exit block"]; + 72 [shape=box label="Exit function test_1"]; + + 4 -> {5}; + 5 -> {6}; + 6 -> {7}; + 7 -> {8}; + 8 -> {9}; + 9 -> {10}; + 10 -> {11 16}; + 11 -> {12}; + 12 -> {13}; + 13 -> {14}; + 14 -> {15}; + 15 -> {30}; + 16 -> {17}; + 17 -> {18}; + 18 -> {19}; + 19 -> {20 25}; + 20 -> {21}; + 21 -> {22}; + 22 -> {23}; + 23 -> {24}; + 24 -> {30}; + 25 -> {26}; + 26 -> {27}; + 27 -> {28}; + 28 -> {29}; + 29 -> {30}; + 30 -> {31}; + 31 -> {32}; + 32 -> {33}; + 33 -> {34}; + 34 -> {35}; + 35 -> {36 39}; + 36 -> {37}; + 37 -> {38}; + 38 -> {70}; + 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43 48}; + 43 -> {44}; + 44 -> {45}; + 45 -> {46}; + 46 -> {47}; + 47 -> {70}; + 48 -> {49}; + 49 -> {50}; + 50 -> {51}; + 51 -> {52 61}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55}; + 55 -> {56}; + 56 -> {57}; + 57 -> {58}; + 58 -> {59}; + 59 -> {60}; + 60 -> {70}; + 61 -> {62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; + 65 -> {66}; + 66 -> {67}; + 67 -> {68}; + 68 -> {69}; + 69 -> {70}; + 70 -> {71}; + 71 -> {72}; +} + +subgraph test_2 { + 73 [shape=box label="Enter function test_2"]; + 74 [shape=box label="Enter block"]; + 75 [shape=box label="Enter when"]; + 76 [shape=box label="Access variable R|/x|"]; + 77 [shape=box label="Enter when branch condition "]; + 78 [shape=box label="Type operator: A"]; + 79 [shape=box label="Exit when branch condition"]; + 80 [shape=box label="Enter block"]; + 81 [shape=box label="Access variable R|/x|"]; + 82 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 83 [shape=box label="Exit block"]; + 84 [shape=box label="Exit when branch result"]; + 85 [shape=box label="Enter when branch condition "]; + 86 [shape=box label="Type operator: B"]; + 87 [shape=box label="Exit when branch condition"]; + 88 [shape=box label="Enter block"]; + 89 [shape=box label="Access variable R|/x|"]; + 90 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 91 [shape=box label="Exit block"]; + 92 [shape=box label="Exit when branch result"]; + 93 [shape=box label="Enter when branch condition else"]; + 94 [shape=box label="Exit when branch condition"]; + 95 [shape=box label="Enter block"]; + 96 [shape=box label="Exit block"]; + 97 [shape=box label="Exit when branch result"]; + 98 [shape=box label="Exit when"]; + 99 [shape=box label="Enter when"]; + 100 [shape=box label="Access variable R|/x|"]; + 101 [shape=box label="Enter when branch condition "]; + 102 [shape=box label="Type operator: A"]; + 103 [shape=box label="Exit when branch condition"]; + 104 [shape=box label="Enter block"]; + 105 [shape=box label="Exit block"]; + 106 [shape=box label="Exit when branch result"]; + 107 [shape=box label="Enter when branch condition "]; + 108 [shape=box label="Type operator: B"]; + 109 [shape=box label="Exit when branch condition"]; + 110 [shape=box label="Enter block"]; + 111 [shape=box label="Access variable R|/x|"]; + 112 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 113 [shape=box label="Exit block"]; + 114 [shape=box label="Exit when branch result"]; + 115 [shape=box label="Enter when branch condition "]; + 116 [shape=box label="Type operator: Int"]; + 117 [shape=box label="Exit when branch condition"]; + 118 [shape=box label="Enter block"]; + 119 [shape=box label="Access variable R|/x|"]; + 120 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 121 [shape=box label="Access variable R|/x|"]; + 122 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 123 [shape=box label="Access variable R|/x|"]; + 124 [shape=box label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 125 [shape=box label="Exit block"]; + 126 [shape=box label="Exit when branch result"]; + 127 [shape=box label="Enter when branch condition else"]; + 128 [shape=box label="Exit when branch condition"]; + 129 [shape=box label="Enter block"]; + 130 [shape=box label="Access variable R|/x|"]; + 131 [shape=box label="Function call: R|/x|.R|/A.foo|()"]; + 132 [shape=box label="Access variable R|/x|"]; + 133 [shape=box label="Function call: R|/x|.R|/B.bar|()"]; + 134 [shape=box label="Exit block"]; + 135 [shape=box label="Exit when branch result"]; + 136 [shape=box label="Exit when"]; + 137 [shape=box label="Exit block"]; + 138 [shape=box label="Exit function test_2"]; + + 73 -> {74}; + 74 -> {75}; + 75 -> {76}; + 76 -> {77}; + 77 -> {78}; + 78 -> {79}; + 79 -> {80 85}; + 80 -> {81}; + 81 -> {82}; + 82 -> {83}; + 83 -> {84}; + 84 -> {98}; + 85 -> {86}; + 86 -> {87}; + 87 -> {88 93}; + 88 -> {89}; + 89 -> {90}; + 90 -> {91}; + 91 -> {92}; + 92 -> {98}; + 93 -> {94}; + 94 -> {95}; + 95 -> {96}; + 96 -> {97}; + 97 -> {98}; + 98 -> {99}; + 99 -> {100}; + 100 -> {101}; + 101 -> {102}; + 102 -> {103}; + 103 -> {104 107}; + 104 -> {105}; + 105 -> {106}; + 106 -> {136}; + 107 -> {108}; + 108 -> {109}; + 109 -> {110 115}; + 110 -> {111}; + 111 -> {112}; + 112 -> {113}; + 113 -> {114}; + 114 -> {136}; + 115 -> {116}; + 116 -> {117}; + 117 -> {118 127}; + 118 -> {119}; + 119 -> {120}; + 120 -> {121}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124}; + 124 -> {125}; + 125 -> {126}; + 126 -> {136}; + 127 -> {128}; + 128 -> {129}; + 129 -> {130}; + 130 -> {131}; + 131 -> {132}; + 132 -> {133}; + 133 -> {134}; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; +} + +subgraph test_3 { + 139 [shape=box label="Enter function test_3"]; + 140 [shape=box label="Enter block"]; + 141 [shape=box label="Enter when"]; + 142 [shape=box label="Access variable R|/x|"]; + 143 [shape=box label="Variable declaration: lval y: R|kotlin/Any?|"]; + 144 [shape=box label="Enter when branch condition "]; + 145 [shape=box label="Type operator: A"]; + 146 [shape=box label="Exit when branch condition"]; + 147 [shape=box label="Enter block"]; + 148 [shape=box label="Access variable R|/x|"]; + 149 [shape=box label="Function call: R|/x|.#()"]; + 150 [shape=box label="Access variable R|/y|"]; + 151 [shape=box label="Function call: R|/y|.R|/A.foo|()"]; + 152 [shape=box label="Exit block"]; + 153 [shape=box label="Exit when branch result"]; + 154 [shape=box label="Enter when branch condition "]; + 155 [shape=box label="Type operator: B"]; + 156 [shape=box label="Exit when branch condition"]; + 157 [shape=box label="Enter block"]; + 158 [shape=box label="Access variable R|/x|"]; + 159 [shape=box label="Function call: R|/x|.#()"]; + 160 [shape=box label="Access variable R|/y|"]; + 161 [shape=box label="Function call: R|/y|.R|/B.bar|()"]; + 162 [shape=box label="Exit block"]; + 163 [shape=box label="Exit when branch result"]; + 164 [shape=box label="Enter when branch condition else"]; + 165 [shape=box label="Exit when branch condition"]; + 166 [shape=box label="Enter block"]; + 167 [shape=box label="Exit block"]; + 168 [shape=box label="Exit when branch result"]; + 169 [shape=box label="Exit when"]; + 170 [shape=box label="Enter when"]; + 171 [shape=box label="Access variable R|/x|"]; + 172 [shape=box label="Variable declaration: lval y: R|kotlin/Any?|"]; + 173 [shape=box label="Enter when branch condition "]; + 174 [shape=box label="Type operator: A"]; + 175 [shape=box label="Exit when branch condition"]; + 176 [shape=box label="Enter block"]; + 177 [shape=box label="Exit block"]; + 178 [shape=box label="Exit when branch result"]; + 179 [shape=box label="Enter when branch condition "]; + 180 [shape=box label="Type operator: B"]; + 181 [shape=box label="Exit when branch condition"]; + 182 [shape=box label="Enter block"]; + 183 [shape=box label="Access variable R|/x|"]; + 184 [shape=box label="Function call: R|/x|.#()"]; + 185 [shape=box label="Access variable R|/y|"]; + 186 [shape=box label="Function call: R|/y|.R|/A.foo|()"]; + 187 [shape=box label="Exit block"]; + 188 [shape=box label="Exit when branch result"]; + 189 [shape=box label="Enter when branch condition "]; + 190 [shape=box label="Type operator: Int"]; + 191 [shape=box label="Exit when branch condition"]; + 192 [shape=box label="Enter block"]; + 193 [shape=box label="Access variable R|/x|"]; + 194 [shape=box label="Function call: R|/x|.#()"]; + 195 [shape=box label="Access variable R|/x|"]; + 196 [shape=box label="Function call: R|/x|.#()"]; + 197 [shape=box label="Access variable R|/x|"]; + 198 [shape=box label="Function call: R|/x|.#()"]; + 199 [shape=box label="Access variable R|/y|"]; + 200 [shape=box label="Function call: R|/y|.R|/A.foo|()"]; + 201 [shape=box label="Access variable R|/y|"]; + 202 [shape=box label="Function call: R|/y|.R|/B.bar|()"]; + 203 [shape=box label="Access variable R|/y|"]; + 204 [shape=box label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 205 [shape=box label="Exit block"]; + 206 [shape=box label="Exit when branch result"]; + 207 [shape=box label="Enter when branch condition else"]; + 208 [shape=box label="Exit when branch condition"]; + 209 [shape=box label="Enter block"]; + 210 [shape=box label="Access variable R|/x|"]; + 211 [shape=box label="Function call: R|/x|.#()"]; + 212 [shape=box label="Access variable R|/x|"]; + 213 [shape=box label="Function call: R|/x|.#()"]; + 214 [shape=box label="Access variable R|/y|"]; + 215 [shape=box label="Function call: R|/y|.R|/A.foo|()"]; + 216 [shape=box label="Access variable R|/y|"]; + 217 [shape=box label="Function call: R|/y|.R|/B.bar|()"]; + 218 [shape=box label="Exit block"]; + 219 [shape=box label="Exit when branch result"]; + 220 [shape=box label="Exit when"]; + 221 [shape=box label="Exit block"]; + 222 [shape=box label="Exit function test_3"]; + + 139 -> {140}; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {144}; + 144 -> {145}; + 145 -> {146}; + 146 -> {147 154}; + 147 -> {148}; + 148 -> {149}; + 149 -> {150}; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; + 153 -> {169}; + 154 -> {155}; + 155 -> {156}; + 156 -> {157 164}; + 157 -> {158}; + 158 -> {159}; + 159 -> {160}; + 160 -> {161}; + 161 -> {162}; + 162 -> {163}; + 163 -> {169}; + 164 -> {165}; + 165 -> {166}; + 166 -> {167}; + 167 -> {168}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {173}; + 173 -> {174}; + 174 -> {175}; + 175 -> {176 179}; + 176 -> {177}; + 177 -> {178}; + 178 -> {220}; + 179 -> {180}; + 180 -> {181}; + 181 -> {182 189}; + 182 -> {183}; + 183 -> {184}; + 184 -> {185}; + 185 -> {186}; + 186 -> {187}; + 187 -> {188}; + 188 -> {220}; + 189 -> {190}; + 190 -> {191}; + 191 -> {192 207}; + 192 -> {193}; + 193 -> {194}; + 194 -> {195}; + 195 -> {196}; + 196 -> {197}; + 197 -> {198}; + 198 -> {199}; + 199 -> {200}; + 200 -> {201}; + 201 -> {202}; + 202 -> {203}; + 203 -> {204}; + 204 -> {205}; + 205 -> {206}; + 206 -> {220}; + 207 -> {208}; + 208 -> {209}; + 209 -> {210}; + 210 -> {211}; + 211 -> {212}; + 212 -> {213}; + 213 -> {214}; + 214 -> {215}; + 215 -> {216}; + 216 -> {217}; + 217 -> {218}; + 218 -> {219}; + 219 -> {220}; + 220 -> {221}; + 221 -> {222}; +} + +subgraph test_4 { + 223 [shape=box label="Enter function test_4"]; + 224 [shape=box label="Enter block"]; + 225 [shape=box label="Enter when"]; + 226 [shape=box label="Access variable R|/x|"]; + 227 [shape=box label="Type operator: x as Int"]; + 228 [shape=box label="Enter when branch condition "]; + 229 [shape=box label="Const: Int(1)"]; + 230 [shape=box label="Operator =="]; + 231 [shape=box label="Exit when branch condition"]; + 232 [shape=box label="Enter block"]; + 233 [shape=box label="Access variable R|/x|"]; + 234 [shape=box label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 235 [shape=box label="Exit block"]; + 236 [shape=box label="Exit when branch result"]; + 237 [shape=box label="Enter when branch condition else"]; + 238 [shape=box label="Exit when branch condition"]; + 239 [shape=box label="Enter block"]; + 240 [shape=box label="Exit block"]; + 241 [shape=box label="Exit when branch result"]; + 242 [shape=box label="Exit when"]; + 243 [shape=box label="Access variable R|/x|"]; + 244 [shape=box label="Function call: R|/x|.R|kotlin/Int.inc|()"]; + 245 [shape=box label="Exit block"]; + 246 [shape=box label="Exit function test_4"]; + + 223 -> {224}; + 224 -> {225}; + 225 -> {226}; + 226 -> {227}; + 227 -> {228}; + 228 -> {229}; + 229 -> {230}; + 230 -> {231}; + 231 -> {232 237}; + 232 -> {233}; + 233 -> {234}; + 234 -> {235}; + 235 -> {236}; + 236 -> {242}; + 237 -> {238}; + 238 -> {239}; + 239 -> {240}; + 240 -> {241}; + 241 -> {242}; + 242 -> {243}; + 243 -> {244}; + 244 -> {245}; + 245 -> {246}; +} + +} diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.kt b/compiler/fir/resolve/testData/resolve/smartcasts/when.kt new file mode 100644 index 00000000000..587bb5c90df --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/when.kt @@ -0,0 +1,91 @@ +interface A { + fun foo() +} + +interface B { + fun bar() +} + +fun test_1(x: Any?) { + when { + x is A -> x.foo() + x is B -> x.bar() + } + + when { + x !is A -> {} + x !is B -> x.foo() + x is Int -> { + x.foo() + x.bar() + x.inc() + } + else -> { + x.foo() + x.bar() + } + } +} + +fun test_2(x: Any?) { + when(x) { + is A -> x.foo() + is B -> x.bar() + } + + when(x) { + !is A -> {} + !is B -> x.foo() + is Int -> { + x.foo() + x.bar() + x.inc() + } + else -> { + x.foo() + x.bar() + } + } +} + +fun test_3(x: Any?) { + when(val y = x) { + is A -> { + x.foo() + y.foo() + } + is B -> { + x.bar() + y.bar() + } + } + + when(val y = x) { + !is A -> {} + !is B -> { + x.foo() + y.foo() + } + is Int -> { + x.foo() + x.bar() + x.inc() + y.foo() + y.bar() + y.inc() + } + else -> { + x.foo() + x.bar() + y.foo() + y.bar() + } + } +} + +fun test_4(x: Any) { + when (x as Int) { + 1 -> x.inc() + } + x.inc() +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/when.txt b/compiler/fir/resolve/testData/resolve/smartcasts/when.txt new file mode 100644 index 00000000000..398d56f733d --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/smartcasts/when.txt @@ -0,0 +1,118 @@ +FILE: when.kt + public abstract interface A : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Unit| + + } + public abstract interface B : R|kotlin/Any| { + public abstract fun bar(): R|kotlin/Unit| + + } + public final fun test_1(x: R|kotlin/Any?|): R|kotlin/Unit| { + when () { + (R|/x| is R|A|) -> { + R|/x|.R|/A.foo|() + } + (R|/x| is R|B|) -> { + R|/x|.R|/B.bar|() + } + else -> { + } + } + + when () { + (R|/x| !is R|A|) -> { + } + (R|/x| !is R|B|) -> { + R|/x|.R|/A.foo|() + } + (R|/x| is R|kotlin/Int|) -> { + R|/x|.R|/A.foo|() + R|/x|.R|/B.bar|() + R|/x|.R|kotlin/Int.inc|() + } + else -> { + R|/x|.R|/A.foo|() + R|/x|.R|/B.bar|() + } + } + + } + public final fun test_2(x: R|kotlin/Any?|): R|kotlin/Unit| { + when (R|/x|) { + ($subj$ is R|A|) -> { + R|/x|.R|/A.foo|() + } + ($subj$ is R|B|) -> { + R|/x|.R|/B.bar|() + } + else -> { + } + } + + when (R|/x|) { + ($subj$ !is R|A|) -> { + } + ($subj$ !is R|B|) -> { + R|/x|.R|/A.foo|() + } + ($subj$ is R|kotlin/Int|) -> { + R|/x|.R|/A.foo|() + R|/x|.R|/B.bar|() + R|/x|.R|kotlin/Int.inc|() + } + else -> { + R|/x|.R|/A.foo|() + R|/x|.R|/B.bar|() + } + } + + } + public final fun test_3(x: R|kotlin/Any?|): R|kotlin/Unit| { + when (lval y: R|kotlin/Any?| = R|/x|) { + ($subj$ is R|A|) -> { + R|/x|.#() + R|/y|.R|/A.foo|() + } + ($subj$ is R|B|) -> { + R|/x|.#() + R|/y|.R|/B.bar|() + } + else -> { + } + } + + when (lval y: R|kotlin/Any?| = R|/x|) { + ($subj$ !is R|A|) -> { + } + ($subj$ !is R|B|) -> { + R|/x|.#() + R|/y|.R|/A.foo|() + } + ($subj$ is R|kotlin/Int|) -> { + R|/x|.#() + R|/x|.#() + R|/x|.#() + R|/y|.R|/A.foo|() + R|/y|.R|/B.bar|() + R|/y|.R|kotlin/Int.inc|() + } + else -> { + R|/x|.#() + R|/x|.#() + R|/y|.R|/A.foo|() + R|/y|.R|/B.bar|() + } + } + + } + public final fun test_4(x: R|kotlin/Any|): R|kotlin/Unit| { + when ((R|/x| as R|kotlin/Int|)) { + ==($subj$, Int(1)) -> { + R|/x|.R|kotlin/Int.inc|() + } + else -> { + } + } + + R|/x|.R|kotlin/Int.inc|() + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java index a933584c1e5..aea185ee899 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java @@ -118,5 +118,10 @@ public class FirCfgBuildingTestGenerated extends AbstractFirCfgBuildingTest { public void testSimpleIf() throws Exception { runTest("compiler/fir/resolve/testData/resolve/smartcasts/simpleIf.kt"); } + + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/smartcasts/when.kt"); + } } }