From 102c9c08d046434dfeb3cc688897ebf24864a6d4 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 30 Jun 2020 15:31:24 +0300 Subject: [PATCH] [FIR] Resolve elvis call as special synthetic call Before that commit we desugared `a ?: b` as when (val elvis = a) { null -> b else -> elvis } It was incorrect, because `a` should be resolved in dependent mode, but when it was `elvis` initializer it was resolved in independent mode, so we can't infer type for `a` in some complex cases --- .../resolve/delegates/delegateWithLambda.txt | 10 +- .../expresssions/syntheticSmartCast.txt | 70 +- .../resolve/inference/lambdaInElvis.kt | 18 + .../resolve/inference/lambdaInElvis.txt | 21 + ...invokeInWhenSubjectVariableInitializer.txt | 10 +- .../boundSmartcasts/boundSmartcasts.dot | 217 +-- .../boundSmartcasts/boundSmartcasts.txt | 10 +- .../smartcasts/controlStructures/elvis.dot | 294 ++- .../smartcasts/controlStructures/elvis.txt | 20 +- .../smartcasts/controlStructures/returns.dot | 109 +- .../smartcasts/controlStructures/returns.txt | 10 +- .../smartcastFromArgument.dot | 105 +- .../smartcastFromArgument.txt | 10 +- .../resolve/smartcasts/nullability.dot | 1598 ++++++++--------- .../resolve/smartcasts/nullability.txt | 20 +- .../smartcasts/safeCalls/assignSafeCall.dot | 426 ++--- .../smartcasts/safeCalls/assignSafeCall.txt | 20 +- .../inference/ifElvisReturn.kt | 18 + .../inference/ifElvisReturn.txt | 20 +- .../resolveWithStdlib/j+k/MapCompute.txt | 10 +- .../fir/FirDiagnosticsTestGenerated.java | 5 + ...DiagnosticsWithLightTreeTestGenerated.java | 5 + ...FirDiagnosticsWithStdlibTestGenerated.java | 5 + .../kotlin/fir/symbols/SyntheticCallableId.kt | 16 +- .../jetbrains/kotlin/fir/dump/HtmlFirDump.kt | 7 + .../kotlin/fir/builder/ConversionUtils.kt | 43 +- .../converter/ExpressionsConverter.kt | 2 +- .../kotlin/fir/builder/RawFirBuilder.kt | 2 +- .../rawBuilder/expressions/nullability.txt | 10 +- .../kotlin/fir/resolve/calls/Arguments.kt | 2 +- .../fir/resolve/calls/CandidateFactory.kt | 3 +- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 31 + .../kotlin/fir/resolve/dfa/cfg/CFGNode.kt | 26 + .../fir/resolve/dfa/cfg/CFGNodeRenderer.kt | 9 +- .../dfa/cfg/ControlFlowGraphBuilder.kt | 32 + .../dfa/cfg/ControlFlowGraphNodeBuilder.kt | 12 + .../dfa/cfg/ControlFlowGraphVisitor.kt | 18 + .../inference/ConstraintSystemCompleter.kt | 6 + ...rCallCompletionResultsWriterTransformer.kt | 19 +- .../transformers/FirSyntheticCallGenerator.kt | 54 + .../body/resolve/FirBodyResolveTransformer.kt | 4 + ...ControlFlowStatementsResolveTransformer.kt | 27 + .../jetbrains/kotlin/fir/types/TypeUtils.kt | 18 +- .../org/jetbrains/kotlin/fir/FirRenderer.kt | 6 + .../discriminatedNothingAndSmartCast.fir.kt | 2 +- .../tests/nullableTypes/uselessElvis.fir.kt | 2 +- .../inferenceForElvis.fir.kt | 4 +- .../diagnostics/notLinked/dfa/pos/32.fir.kt | 2 +- 48 files changed, 1560 insertions(+), 1828 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.txt create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/delegates/delegateWithLambda.txt b/compiler/fir/analysis-tests/testData/resolve/delegates/delegateWithLambda.txt index df942a37af9..3ef531fe1e7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/delegates/delegateWithLambda.txt +++ b/compiler/fir/analysis-tests/testData/resolve/delegates/delegateWithLambda.txt @@ -24,15 +24,7 @@ FILE: delegateWithLambda.kt } public final val x: R|kotlin/String|by R|/lazy|( = lazy@fun (): R|kotlin/String| { - lval y: R|kotlin/String| = when (lval : R|kotlin/String?| = (R|/getAny|() as? R|kotlin/String|)) { - ==($subj$, Null(null)) -> { - String() - } - else -> { - R|/| - } - } - + lval y: R|kotlin/String| = (R|/getAny|() as? R|kotlin/String|) ?: String() ^ R|/y| } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/syntheticSmartCast.txt b/compiler/fir/analysis-tests/testData/resolve/expresssions/syntheticSmartCast.txt index 40a02dfeb38..8e382a362ea 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/syntheticSmartCast.txt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/syntheticSmartCast.txt @@ -16,27 +16,11 @@ FILE: test.kt } public final fun test1(x: R|AnotherClass?|): R|kotlin/Unit| { - lval bar: R|kotlin/CharSequence| = when (lval : R|kotlin/CharSequence?| = R|/x|?.{ $subj$.R|/AnotherClass.bar| }) { - ==($subj$, Null(null)) -> { - ^test1 Unit - } - else -> { - R|/| - } - } - + lval bar: R|kotlin/CharSequence| = R|/x|?.{ $subj$.R|/AnotherClass.bar| } ?: ^test1 Unit R|/x|.R|/AnotherClass.bar| } public final fun test2(x: R|SomeClass?|): R|kotlin/Unit| { - lval bar: R|kotlin/CharSequence| = when (lval : R|kotlin/CharSequence?| = R|/x|?.{ $subj$.R|/SomeClass.bar| }) { - ==($subj$, Null(null)) -> { - ^test2 Unit - } - else -> { - R|/| - } - } - + lval bar: R|kotlin/CharSequence| = R|/x|?.{ $subj$.R|/SomeClass.bar| } ?: ^test2 Unit R|/x|.R|/SomeClass.bar| } public final fun test3(x: R|AnotherClass?|): R|kotlin/Unit| { @@ -58,62 +42,22 @@ FILE: test.kt } public final fun test5(x: R|AnotherClass?|): R|kotlin/Unit| { - lval bar: R|kotlin/String| = when (lval : R|kotlin/String?| = (R|/x|?.{ $subj$.R|/AnotherClass.bar| } as? R|kotlin/String|)) { - ==($subj$, Null(null)) -> { - ^test5 Unit - } - else -> { - R|/| - } - } - + lval bar: R|kotlin/String| = (R|/x|?.{ $subj$.R|/AnotherClass.bar| } as? R|kotlin/String|) ?: ^test5 Unit R|/x|.R|/AnotherClass.foo| } public final fun test6(x: R|SomeClass?|): R|kotlin/Unit| { - lval bar: R|kotlin/String| = when (lval : R|kotlin/String?| = (R|/x|?.{ $subj$.R|/SomeClass.bar| } as? R|kotlin/String|)) { - ==($subj$, Null(null)) -> { - ^test6 Unit - } - else -> { - R|/| - } - } - + lval bar: R|kotlin/String| = (R|/x|?.{ $subj$.R|/SomeClass.bar| } as? R|kotlin/String|) ?: ^test6 Unit R|/x|.R|/SomeClass.foo| } public final fun test7(x: R|AnotherClass?|): R|kotlin/Unit| { - lval baz: R|kotlin/Boolean| = when (lval : R|kotlin/Boolean?| = (R|/x|?.{ $subj$.R|/AnotherClass.baz|() } as? R|kotlin/Boolean|)) { - ==($subj$, Null(null)) -> { - ^test7 Unit - } - else -> { - R|/| - } - } - + lval baz: R|kotlin/Boolean| = (R|/x|?.{ $subj$.R|/AnotherClass.baz|() } as? R|kotlin/Boolean|) ?: ^test7 Unit R|/x|.R|/AnotherClass.foo| } public final fun test8(x: R|AnotherClass?|): R|kotlin/Unit| { - lval bar: R|kotlin/CharSequence| = when (lval : R|kotlin/CharSequence?| = R|/x|?.{ $subj$.R|/AnotherClass.bar| }) { - ==($subj$, Null(null)) -> { - ^test8 Unit - } - else -> { - R|/| - } - } - + lval bar: R|kotlin/CharSequence| = R|/x|?.{ $subj$.R|/AnotherClass.bar| } ?: ^test8 Unit R|/x|.R|/AnotherClass.foo| } public final fun test9(x: R|AnotherClass?|): R|kotlin/Unit| { - lval baz: R|kotlin/Any| = when (lval : R|kotlin/Any?| = R|/x|?.{ $subj$.R|/AnotherClass.baz|() }) { - ==($subj$, Null(null)) -> { - ^test9 Unit - } - else -> { - R|/| - } - } - + lval baz: R|kotlin/Any| = R|/x|?.{ $subj$.R|/AnotherClass.baz|() } ?: ^test9 Unit R|/x|.R|/AnotherClass.foo| } diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt b/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt new file mode 100644 index 00000000000..04a501e1371 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt @@ -0,0 +1,18 @@ +// ISSUE: KT-39012 + +interface A + +fun foo(f: (MutableList) -> Unit): List? = TODO() +fun listOf(): List = TODO() + +fun bar1(w: List): List? { + return foo { container -> + container.add("") + } ?: w +} + +fun bar2(): List? { + return foo { container -> + container.add("") + } ?: listOf() +} diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.txt b/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.txt new file mode 100644 index 00000000000..90c2359ee66 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.txt @@ -0,0 +1,21 @@ +FILE: lambdaInElvis.kt + public abstract interface A : R|kotlin/Any| { + } + public final fun foo(f: R|(kotlin/collections/MutableList) -> kotlin/Unit|): R|kotlin/collections/List?| { + ^foo R|kotlin/TODO|() + } + public final fun listOf(): R|kotlin/collections/List| { + ^listOf R|kotlin/TODO|() + } + public final fun bar1(w: R|kotlin/collections/List|): R|kotlin/collections/List?| { + ^bar1 R|/foo|( = foo@fun (container: R|kotlin/collections/MutableList|): R|kotlin/Unit| { + ^ R|/container|.R|FakeOverride|(String()) + } + ) ?: R|/w| + } + public final fun bar2(): R|kotlin/collections/List?| { + ^bar2 R|/foo|( = foo@fun (container: R|kotlin/collections/MutableList|): R|kotlin/Unit| { + ^ R|/container|.R|FakeOverride|(String()) + } + ) ?: R|/listOf|() + } diff --git a/compiler/fir/analysis-tests/testData/resolve/invokeInWhenSubjectVariableInitializer.txt b/compiler/fir/analysis-tests/testData/resolve/invokeInWhenSubjectVariableInitializer.txt index 19d74110a31..2f43ac33bf6 100644 --- a/compiler/fir/analysis-tests/testData/resolve/invokeInWhenSubjectVariableInitializer.txt +++ b/compiler/fir/analysis-tests/testData/resolve/invokeInWhenSubjectVariableInitializer.txt @@ -1,12 +1,4 @@ FILE: invokeInWhenSubjectVariableInitializer.kt public final fun test(func: R|() -> kotlin/String?|): R|kotlin/Unit| { - lval x: R|kotlin/String| = when (lval : R|kotlin/String?| = R|/func|.R|FakeOverride|()) { - ==($subj$, Null(null)) -> { - String() - } - else -> { - R|/| - } - } - + lval x: R|kotlin/String| = R|/func|.R|FakeOverride|() ?: String() } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot index 700f035fefd..2d49886cd58 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.dot @@ -366,81 +366,75 @@ digraph boundSmartcasts_kt { subgraph cluster_34 { color=blue 130 [label="Enter block"]; - subgraph cluster_35 { - color=blue - 131 [label="Enter when"]; - 132 [label="Access variable R|/d|"]; - 133 [label="Access variable R|/D.any|"]; - 134 [label="Variable declaration: lval : R|kotlin/Any?|"]; - subgraph cluster_36 { - color=blue - 135 [label="Enter when branch condition "]; - 136 [label="Const: Null(null)"]; - 137 [label="Operator =="]; - 138 [label="Exit when branch condition"]; - } - subgraph cluster_37 { - color=blue - 139 [label="Enter when branch condition else"]; - 140 [label="Exit when branch condition"]; - } - 141 [label="Enter when branch result"]; - subgraph cluster_38 { - color=blue - 142 [label="Enter block"]; - 143 [label="Access variable R|/|"]; - 144 [label="Exit block"]; - } - 145 [label="Exit when branch result"]; - 146 [label="Enter when branch result"]; - subgraph cluster_39 { - color=blue - 147 [label="Enter block"]; - 148 [label="Jump: ^test_5 Unit"]; - 149 [label="Stub" style="filled" fillcolor=gray]; - 150 [label="Exit block" style="filled" fillcolor=gray]; - } - 151 [label="Exit when branch result" style="filled" fillcolor=gray]; - 152 [label="Exit when"]; - } - 153 [label="Variable declaration: lval a: R|kotlin/Any|"]; - 154 [label="Access variable R|/a|"]; - 155 [label="Function call: R|/a|.R|/baz|()"]; - 156 [label="Access variable R|/d|"]; - 157 [label="Access variable R|/D.any|"]; - 158 [label="Function call: R|/d|.R|/D.any|.R|/baz|()"]; - 159 [label="Access variable R|/a|"]; - 160 [label="Type operator: (R|/a| as R|A|)"]; - 161 [label="Access variable R|/a|"]; - 162 [label="Function call: R|/a|.R|/A.foo|()"]; - 163 [label="Exit block"]; + 131 [label="Access variable R|/d|"]; + 132 [label="Access variable R|/D.any|"]; + 133 [label="Exit lhs of ?:"]; + 134 [label="Enter rhs of ?:"]; + 135 [label="Jump: ^test_5 Unit"]; + 136 [label="Stub" style="filled" fillcolor=gray]; + 137 [label="Lhs of ?: is not null"]; + 138 [label="Exit ?:"]; + 139 [label="Variable declaration: lval a: R|kotlin/Any|"]; + 140 [label="Access variable R|/a|"]; + 141 [label="Function call: R|/a|.R|/baz|()"]; + 142 [label="Access variable R|/d|"]; + 143 [label="Access variable R|/D.any|"]; + 144 [label="Function call: R|/d|.R|/D.any|.R|/baz|()"]; + 145 [label="Access variable R|/a|"]; + 146 [label="Type operator: (R|/a| as R|A|)"]; + 147 [label="Access variable R|/a|"]; + 148 [label="Function call: R|/a|.R|/A.foo|()"]; + 149 [label="Exit block"]; } - 164 [label="Exit function test_5" style="filled" fillcolor=red]; + 150 [label="Exit function test_5" style="filled" fillcolor=red]; } 129 -> {130}; 130 -> {131}; 131 -> {132}; 132 -> {133}; - 133 -> {134}; + 133 -> {137 134}; 134 -> {135}; - 135 -> {136}; - 136 -> {137}; + 135 -> {150}; + 135 -> {136} [style=dotted]; + 136 -> {138} [style=dotted]; 137 -> {138}; - 138 -> {146 139}; + 138 -> {139}; 139 -> {140}; 140 -> {141}; 141 -> {142}; 142 -> {143}; 143 -> {144}; 144 -> {145}; - 145 -> {152}; + 145 -> {146}; 146 -> {147}; 147 -> {148}; - 148 -> {164}; - 148 -> {149} [style=dotted]; - 149 -> {150} [style=dotted]; - 150 -> {151} [style=dotted]; - 151 -> {152} [style=dotted]; + 148 -> {149}; + 149 -> {150}; + + subgraph cluster_35 { + color=red + 151 [label="Enter function test_6" style="filled" fillcolor=red]; + subgraph cluster_36 { + color=blue + 152 [label="Enter block"]; + 153 [label="Access variable R|/d1|"]; + 154 [label="Access variable R|/D.any|"]; + 155 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 156 [label="Access variable R|/a|"]; + 157 [label="Type operator: (R|/a| as R|A|)"]; + 158 [label="Access variable R|/a|"]; + 159 [label="Function call: R|/a|.R|/A.foo|()"]; + 160 [label="Access variable R|/d1|"]; + 161 [label="Access variable R|/D.any|"]; + 162 [label="Function call: R|/d1|.R|/D.any|.R|/A.foo|()"]; + 163 [label="Access variable R|/d1|"]; + 164 [label="Access variable R|/D.any|"]; + 165 [label="Function call: R|/d1|.R|/D.any|.R|/baz|()"]; + 166 [label="Exit block"]; + } + 167 [label="Exit function test_6" style="filled" fillcolor=red]; + } + 151 -> {152}; 152 -> {153}; 153 -> {154}; 154 -> {155}; @@ -453,95 +447,58 @@ digraph boundSmartcasts_kt { 161 -> {162}; 162 -> {163}; 163 -> {164}; - - subgraph cluster_40 { - color=red - 165 [label="Enter function test_6" style="filled" fillcolor=red]; - subgraph cluster_41 { - color=blue - 166 [label="Enter block"]; - 167 [label="Access variable R|/d1|"]; - 168 [label="Access variable R|/D.any|"]; - 169 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 170 [label="Access variable R|/a|"]; - 171 [label="Type operator: (R|/a| as R|A|)"]; - 172 [label="Access variable R|/a|"]; - 173 [label="Function call: R|/a|.R|/A.foo|()"]; - 174 [label="Access variable R|/d1|"]; - 175 [label="Access variable R|/D.any|"]; - 176 [label="Function call: R|/d1|.R|/D.any|.R|/A.foo|()"]; - 177 [label="Access variable R|/d1|"]; - 178 [label="Access variable R|/D.any|"]; - 179 [label="Function call: R|/d1|.R|/D.any|.R|/baz|()"]; - 180 [label="Exit block"]; - } - 181 [label="Exit function test_6" style="filled" fillcolor=red]; - } + 164 -> {165}; 165 -> {166}; 166 -> {167}; - 167 -> {168}; + + subgraph cluster_37 { + color=red + 168 [label="Enter function test_7" style="filled" fillcolor=red]; + subgraph cluster_38 { + color=blue + 169 [label="Enter block"]; + 170 [label="Access variable R|/d1|"]; + 171 [label="Enter safe call"]; + 172 [label="Access variable R|/D.any|"]; + 173 [label="Exit safe call"]; + 174 [label="Variable declaration: lval a: R|kotlin/Any?|"]; + 175 [label="Access variable R|/d2|"]; + 176 [label="Enter safe call"]; + 177 [label="Access variable R|/D.any|"]; + 178 [label="Exit safe call"]; + 179 [label="Variable declaration: lval b: R|kotlin/Any?|"]; + 180 [label="Access variable R|/a|"]; + 181 [label="Type operator: (R|/a| as R|A|)"]; + 182 [label="Access variable R|/a|"]; + 183 [label="Function call: R|/a|.R|/A.foo|()"]; + 184 [label="Access variable R|/b|"]; + 185 [label="Type operator: (R|/b| as R|B|)"]; + 186 [label="Access variable R|/b|"]; + 187 [label="Function call: R|/b|.R|/B.bar|()"]; + 188 [label="Exit block"]; + } + 189 [label="Exit function test_7" style="filled" fillcolor=red]; + } 168 -> {169}; 169 -> {170}; - 170 -> {171}; + 170 -> {171 173}; 171 -> {172}; 172 -> {173}; 173 -> {174}; 174 -> {175}; - 175 -> {176}; + 175 -> {176 178}; 176 -> {177}; 177 -> {178}; 178 -> {179}; 179 -> {180}; 180 -> {181}; - - subgraph cluster_42 { - color=red - 182 [label="Enter function test_7" style="filled" fillcolor=red]; - subgraph cluster_43 { - color=blue - 183 [label="Enter block"]; - 184 [label="Access variable R|/d1|"]; - 185 [label="Enter safe call"]; - 186 [label="Access variable R|/D.any|"]; - 187 [label="Exit safe call"]; - 188 [label="Variable declaration: lval a: R|kotlin/Any?|"]; - 189 [label="Access variable R|/d2|"]; - 190 [label="Enter safe call"]; - 191 [label="Access variable R|/D.any|"]; - 192 [label="Exit safe call"]; - 193 [label="Variable declaration: lval b: R|kotlin/Any?|"]; - 194 [label="Access variable R|/a|"]; - 195 [label="Type operator: (R|/a| as R|A|)"]; - 196 [label="Access variable R|/a|"]; - 197 [label="Function call: R|/a|.R|/A.foo|()"]; - 198 [label="Access variable R|/b|"]; - 199 [label="Type operator: (R|/b| as R|B|)"]; - 200 [label="Access variable R|/b|"]; - 201 [label="Function call: R|/b|.R|/B.bar|()"]; - 202 [label="Exit block"]; - } - 203 [label="Exit function test_7" style="filled" fillcolor=red]; - } + 181 -> {182}; 182 -> {183}; 183 -> {184}; - 184 -> {185 187}; + 184 -> {185}; 185 -> {186}; 186 -> {187}; 187 -> {188}; 188 -> {189}; - 189 -> {190 192}; - 190 -> {191}; - 191 -> {192}; - 192 -> {193}; - 193 -> {194}; - 194 -> {195}; - 195 -> {196}; - 196 -> {197}; - 197 -> {198}; - 198 -> {199}; - 199 -> {200}; - 200 -> {201}; - 201 -> {202}; - 202 -> {203}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt index 3a831b9363a..a251fe3f09e 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcasts.txt @@ -70,15 +70,7 @@ FILE: boundSmartcasts.kt public final fun R|kotlin/Any|.baz(): R|kotlin/Unit| { } public final fun test_5(d: R|D|): R|kotlin/Unit| { - lval a: R|kotlin/Any| = when (lval : R|kotlin/Any?| = R|/d|.R|/D.any|) { - ==($subj$, Null(null)) -> { - ^test_5 Unit - } - else -> { - R|/| - } - } - + lval a: R|kotlin/Any| = R|/d|.R|/D.any| ?: ^test_5 Unit R|/a|.R|/baz|() R|/d|.R|/D.any|.R|/baz|() (R|/a| as R|A|) diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.dot index 0c7adb0ee8b..d7945e51496 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.dot @@ -36,122 +36,102 @@ digraph elvis_kt { subgraph cluster_6 { color=blue 9 [label="Enter when branch condition "]; - subgraph cluster_7 { - color=blue - 10 [label="Enter when"]; - 11 [label="Access variable R|/x|"]; - 12 [label="Enter safe call"]; - 13 [label="Access variable R|/A.b|"]; - 14 [label="Exit safe call"]; - 15 [label="Variable declaration: lval : R|kotlin/Boolean?|"]; - subgraph cluster_8 { - color=blue - 16 [label="Enter when branch condition "]; - 17 [label="Const: Null(null)"]; - 18 [label="Operator =="]; - 19 [label="Exit when branch condition"]; - } - subgraph cluster_9 { - color=blue - 20 [label="Enter when branch condition else"]; - 21 [label="Exit when branch condition"]; - } - 22 [label="Enter when branch result"]; - subgraph cluster_10 { - color=blue - 23 [label="Enter block"]; - 24 [label="Access variable R|/|"]; - 25 [label="Exit block"]; - } - 26 [label="Exit when branch result"]; - 27 [label="Enter when branch result"]; - subgraph cluster_11 { - color=blue - 28 [label="Enter block"]; - 29 [label="Jump: ^test_1 Unit"]; - 30 [label="Stub" style="filled" fillcolor=gray]; - 31 [label="Exit block" style="filled" fillcolor=gray]; - } - 32 [label="Exit when branch result" style="filled" fillcolor=gray]; - 33 [label="Exit when"]; - } - 34 [label="Exit when branch condition"]; + 10 [label="Access variable R|/x|"]; + 11 [label="Enter safe call"]; + 12 [label="Access variable R|/A.b|"]; + 13 [label="Exit safe call"]; + 14 [label="Exit lhs of ?:"]; + 15 [label="Enter rhs of ?:"]; + 16 [label="Jump: ^test_1 Unit"]; + 17 [label="Stub" style="filled" fillcolor=gray]; + 18 [label="Lhs of ?: is not null"]; + 19 [label="Exit ?:"]; + 20 [label="Exit when branch condition"]; } - 35 [label="Synthetic else branch"]; - 36 [label="Enter when branch result"]; - subgraph cluster_12 { + 21 [label="Synthetic else branch"]; + 22 [label="Enter when branch result"]; + subgraph cluster_7 { color=blue - 37 [label="Enter block"]; - 38 [label="Access variable R|/x|"]; - 39 [label="Function call: R|/x|.R|/A.foo|()"]; - 40 [label="Exit block"]; + 23 [label="Enter block"]; + 24 [label="Access variable R|/x|"]; + 25 [label="Function call: R|/x|.R|/A.foo|()"]; + 26 [label="Exit block"]; } - 41 [label="Exit when branch result"]; - 42 [label="Exit when"]; + 27 [label="Exit when branch result"]; + 28 [label="Exit when"]; } - 43 [label="Exit block"]; + 29 [label="Exit block"]; } - 44 [label="Exit function test_1" style="filled" fillcolor=red]; + 30 [label="Exit function test_1" style="filled" fillcolor=red]; } 6 -> {7}; 7 -> {8}; 8 -> {9}; 9 -> {10}; - 10 -> {11}; - 11 -> {12 14}; + 10 -> {11 13}; + 11 -> {12}; 12 -> {13}; 13 -> {14}; - 14 -> {15}; + 14 -> {18 15}; 15 -> {16}; - 16 -> {17}; - 17 -> {18}; + 16 -> {30}; + 16 -> {17} [style=dotted]; + 17 -> {19} [style=dotted]; 18 -> {19}; - 19 -> {27 20}; - 20 -> {21}; - 21 -> {22}; + 19 -> {20}; + 20 -> {22 21}; + 21 -> {28}; 22 -> {23}; 23 -> {24}; 24 -> {25}; 25 -> {26}; - 26 -> {33}; + 26 -> {27}; 27 -> {28}; 28 -> {29}; - 29 -> {44}; - 29 -> {30} [style=dotted]; - 30 -> {31} [style=dotted]; - 31 -> {32} [style=dotted]; - 32 -> {33} [style=dotted]; - 33 -> {34}; - 34 -> {36 35}; - 35 -> {42}; - 36 -> {37}; - 37 -> {38}; - 38 -> {39}; - 39 -> {40}; - 40 -> {41}; - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; + 29 -> {30}; - subgraph cluster_13 { + subgraph cluster_8 { color=red - 45 [label="Enter function test2" style="filled" fillcolor=red]; - subgraph cluster_14 { + 31 [label="Enter function test2" style="filled" fillcolor=red]; + subgraph cluster_9 { color=blue - 46 [label="Enter block"]; - subgraph cluster_15 { + 32 [label="Enter block"]; + subgraph cluster_10 { + color=blue + 33 [label="Enter when"]; + subgraph cluster_11 { + color=blue + 34 [label="Enter when branch condition "]; + 35 [label="Access variable R|/b|"]; + 36 [label="Type operator: (R|/b| !is R|kotlin/String|)"]; + 37 [label="Exit when branch condition"]; + } + 38 [label="Synthetic else branch"]; + 39 [label="Enter when branch result"]; + subgraph cluster_12 { + color=blue + 40 [label="Enter block"]; + 41 [label="Const: String()"]; + 42 [label="Jump: ^test2 String()"]; + 43 [label="Stub" style="filled" fillcolor=gray]; + 44 [label="Exit block" style="filled" fillcolor=gray]; + } + 45 [label="Exit when branch result" style="filled" fillcolor=gray]; + 46 [label="Exit when"]; + } + subgraph cluster_13 { color=blue 47 [label="Enter when"]; - subgraph cluster_16 { + subgraph cluster_14 { color=blue 48 [label="Enter when branch condition "]; - 49 [label="Access variable R|/b|"]; - 50 [label="Type operator: (R|/b| !is R|kotlin/String|)"]; + 49 [label="Access variable R|/a|"]; + 50 [label="Type operator: (R|/a| !is R|kotlin/String?|)"]; 51 [label="Exit when branch condition"]; } 52 [label="Synthetic else branch"]; 53 [label="Enter when branch result"]; - subgraph cluster_17 { + subgraph cluster_15 { color=blue 54 [label="Enter block"]; 55 [label="Const: String()"]; @@ -162,79 +142,34 @@ digraph elvis_kt { 59 [label="Exit when branch result" style="filled" fillcolor=gray]; 60 [label="Exit when"]; } - subgraph cluster_18 { - color=blue - 61 [label="Enter when"]; - subgraph cluster_19 { - color=blue - 62 [label="Enter when branch condition "]; - 63 [label="Access variable R|/a|"]; - 64 [label="Type operator: (R|/a| !is R|kotlin/String?|)"]; - 65 [label="Exit when branch condition"]; - } - 66 [label="Synthetic else branch"]; - 67 [label="Enter when branch result"]; - subgraph cluster_20 { - color=blue - 68 [label="Enter block"]; - 69 [label="Const: String()"]; - 70 [label="Jump: ^test2 String()"]; - 71 [label="Stub" style="filled" fillcolor=gray]; - 72 [label="Exit block" style="filled" fillcolor=gray]; - } - 73 [label="Exit when branch result" style="filled" fillcolor=gray]; - 74 [label="Exit when"]; - } - subgraph cluster_21 { - color=blue - 75 [label="Enter when"]; - 76 [label="Access variable R|/a|"]; - 77 [label="Variable declaration: lval : R|kotlin/String?|"]; - subgraph cluster_22 { - color=blue - 78 [label="Enter when branch condition "]; - 79 [label="Const: Null(null)"]; - 80 [label="Operator =="]; - 81 [label="Exit when branch condition"]; - } - subgraph cluster_23 { - color=blue - 82 [label="Enter when branch condition else"]; - 83 [label="Exit when branch condition"]; - } - 84 [label="Enter when branch result"]; - subgraph cluster_24 { - color=blue - 85 [label="Enter block"]; - 86 [label="Access variable R|/|"]; - 87 [label="Exit block"]; - } - 88 [label="Exit when branch result"]; - 89 [label="Enter when branch result"]; - subgraph cluster_25 { - color=blue - 90 [label="Enter block"]; - 91 [label="Access variable R|/b|"]; - 92 [label="Exit block"]; - } - 93 [label="Exit when branch result"]; - 94 [label="Exit when"]; - } - 95 [label="Jump: ^test2 when (lval : R|kotlin/String?| = R|/a|) { - ==($subj$, Null(null)) -> { - R|/b| - } - else -> { - R|/| - } -} -"]; - 96 [label="Stub" style="filled" fillcolor=gray]; - 97 [label="Exit block" style="filled" fillcolor=gray]; + 61 [label="Access variable R|/a|"]; + 62 [label="Exit lhs of ?:"]; + 63 [label="Enter rhs of ?:"]; + 64 [label="Access variable R|/b|"]; + 65 [label="Lhs of ?: is not null"]; + 66 [label="Exit ?:"]; + 67 [label="Jump: ^test2 R|/a| ?: R|/b|"]; + 68 [label="Stub" style="filled" fillcolor=gray]; + 69 [label="Exit block" style="filled" fillcolor=gray]; } - 98 [label="Exit function test2" style="filled" fillcolor=red]; + 70 [label="Exit function test2" style="filled" fillcolor=red]; } - 45 -> {46}; + 31 -> {32}; + 32 -> {33}; + 33 -> {34}; + 34 -> {35}; + 35 -> {36}; + 36 -> {37}; + 37 -> {39 38}; + 38 -> {46}; + 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {70}; + 42 -> {43} [style=dotted]; + 43 -> {44} [style=dotted]; + 44 -> {45} [style=dotted]; + 45 -> {46} [style=dotted]; 46 -> {47}; 47 -> {48}; 48 -> {49}; @@ -245,50 +180,21 @@ digraph elvis_kt { 53 -> {54}; 54 -> {55}; 55 -> {56}; - 56 -> {98}; + 56 -> {70}; 56 -> {57} [style=dotted]; 57 -> {58} [style=dotted]; 58 -> {59} [style=dotted]; 59 -> {60} [style=dotted]; 60 -> {61}; 61 -> {62}; - 62 -> {63}; + 62 -> {65 63}; 63 -> {64}; - 64 -> {65}; - 65 -> {67 66}; - 66 -> {74}; - 67 -> {68}; - 68 -> {69}; - 69 -> {70}; - 70 -> {98}; - 70 -> {71} [style=dotted]; - 71 -> {72} [style=dotted]; - 72 -> {73} [style=dotted]; - 73 -> {74} [style=dotted]; - 74 -> {75}; - 75 -> {76}; - 76 -> {77}; - 77 -> {78}; - 78 -> {79}; - 79 -> {80}; - 80 -> {81}; - 81 -> {89 82}; - 82 -> {83}; - 83 -> {84}; - 84 -> {85}; - 85 -> {86}; - 86 -> {87}; - 87 -> {88}; - 88 -> {94}; - 89 -> {90}; - 90 -> {91}; - 91 -> {92}; - 92 -> {93}; - 93 -> {94}; - 94 -> {95}; - 95 -> {98}; - 95 -> {96} [style=dotted]; - 96 -> {97} [style=dotted]; - 97 -> {98} [style=dotted]; + 64 -> {66}; + 65 -> {66}; + 66 -> {67}; + 67 -> {70}; + 67 -> {68} [style=dotted]; + 68 -> {69} [style=dotted]; + 69 -> {70} [style=dotted]; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.txt index 4b6c9aeb036..c533876ed78 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/elvis.txt @@ -8,15 +8,7 @@ FILE: elvis.kt } public final fun test_1(x: R|A?|): R|kotlin/Unit| { when () { - when (lval : R|kotlin/Boolean?| = R|/x|?.{ $subj$.R|/A.b| }) { - ==($subj$, Null(null)) -> { - ^test_1 Unit - } - else -> { - R|/| - } - } - -> { + R|/x|?.{ $subj$.R|/A.b| } ?: ^test_1 Unit -> { R|/x|.R|/A.foo|() } } @@ -35,13 +27,5 @@ FILE: elvis.kt } } - ^test2 when (lval : R|kotlin/String?| = R|/a|) { - ==($subj$, Null(null)) -> { - R|/b| - } - else -> { - R|/| - } - } - + ^test2 R|/a| ?: R|/b| } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.dot index b3b74fb28f1..217b0b2f6e1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.dot @@ -434,104 +434,61 @@ digraph returns_kt { 151 [label="Access variable R|/a|"]; 152 [label="Type operator: (R|/a| as? R|kotlin/String|)"]; 153 [label="Variable declaration: lval s: R|kotlin/String?|"]; + 154 [label="Access variable R|/s|"]; + 155 [label="Enter safe call"]; + 156 [label="Access variable R|/ext|"]; + 157 [label="Exit safe call"]; + 158 [label="Exit lhs of ?:"]; + 159 [label="Enter rhs of ?:"]; + 160 [label="Jump: ^test_4 Unit"]; + 161 [label="Stub" style="filled" fillcolor=gray]; + 162 [label="Lhs of ?: is not null"]; + 163 [label="Exit ?:"]; + 164 [label="Variable declaration: lval length: R|kotlin/Int|"]; + 165 [label="Postponed enter to lambda"]; subgraph cluster_42 { color=blue - 154 [label="Enter when"]; - 155 [label="Access variable R|/s|"]; - 156 [label="Enter safe call"]; - 157 [label="Access variable R|/ext|"]; - 158 [label="Exit safe call"]; - 159 [label="Variable declaration: lval : R|kotlin/Int?|"]; + 170 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; subgraph cluster_43 { color=blue - 160 [label="Enter when branch condition "]; - 161 [label="Const: Null(null)"]; - 162 [label="Operator =="]; - 163 [label="Exit when branch condition"]; + 171 [label="Enter block"]; + 172 [label="Access variable R|/s|"]; + 173 [label="Access variable R|kotlin/String.length|"]; + 174 [label="Exit block"]; } - subgraph cluster_44 { - color=blue - 164 [label="Enter when branch condition else"]; - 165 [label="Exit when branch condition"]; - } - 166 [label="Enter when branch result"]; - subgraph cluster_45 { - color=blue - 167 [label="Enter block"]; - 168 [label="Access variable R|/|"]; - 169 [label="Exit block"]; - } - 170 [label="Exit when branch result"]; - 171 [label="Enter when branch result"]; - subgraph cluster_46 { - color=blue - 172 [label="Enter block"]; - 173 [label="Jump: ^test_4 Unit"]; - 174 [label="Stub" style="filled" fillcolor=gray]; - 175 [label="Exit block" style="filled" fillcolor=gray]; - } - 176 [label="Exit when branch result" style="filled" fillcolor=gray]; - 177 [label="Exit when"]; + 175 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 178 [label="Variable declaration: lval length: R|kotlin/Int|"]; - 179 [label="Postponed enter to lambda"]; - subgraph cluster_47 { - color=blue - 184 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - subgraph cluster_48 { - color=blue - 185 [label="Enter block"]; - 186 [label="Access variable R|/s|"]; - 187 [label="Access variable R|kotlin/String.length|"]; - 188 [label="Exit block"]; - } - 189 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; - } - 180 [label="Postponed exit from lambda"]; - 181 [label="Function call: R|/runHigherOrder|(...)"]; - 182 [label="Exit block"]; + 166 [label="Postponed exit from lambda"]; + 167 [label="Function call: R|/runHigherOrder|(...)"]; + 168 [label="Exit block"]; } - 183 [label="Exit function test_4" style="filled" fillcolor=red]; + 169 [label="Exit function test_4" style="filled" fillcolor=red]; } 149 -> {150}; 150 -> {151}; 151 -> {152}; 152 -> {153}; 153 -> {154}; - 154 -> {155}; - 155 -> {156 158}; + 154 -> {155 157}; + 155 -> {156}; 156 -> {157}; 157 -> {158}; - 158 -> {159}; + 158 -> {162 159}; 159 -> {160}; - 160 -> {161}; - 161 -> {162}; + 160 -> {169}; + 160 -> {161} [style=dotted]; + 161 -> {163} [style=dotted]; 162 -> {163}; - 163 -> {171 164}; + 163 -> {164}; 164 -> {165}; - 165 -> {166}; + 165 -> {166 170}; 166 -> {167}; 167 -> {168}; 168 -> {169}; - 169 -> {170}; - 170 -> {177}; + 170 -> {171}; 171 -> {172}; 172 -> {173}; - 173 -> {183}; - 173 -> {174} [style=dotted]; - 174 -> {175} [style=dotted]; - 175 -> {176} [style=dotted]; - 176 -> {177} [style=dotted]; - 177 -> {178}; - 178 -> {179}; - 179 -> {180 184}; - 180 -> {181}; - 181 -> {182}; - 182 -> {183}; - 184 -> {185}; - 185 -> {186}; - 186 -> {187}; - 187 -> {188}; - 188 -> {189}; + 173 -> {174}; + 174 -> {175}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.txt index f97e358abbe..cedc017b569 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/returns.txt @@ -74,15 +74,7 @@ FILE: returns.kt } public final fun test_4(a: R|kotlin/Any?|): R|kotlin/Unit| { lval s: R|kotlin/String?| = (R|/a| as? R|kotlin/String|) - lval length: R|kotlin/Int| = when (lval : R|kotlin/Int?| = R|/s|?.{ $subj$.R|/ext| }) { - ==($subj$, Null(null)) -> { - ^test_4 Unit - } - else -> { - R|/| - } - } - + lval length: R|kotlin/Int| = R|/s|?.{ $subj$.R|/ext| } ?: ^test_4 Unit R|/runHigherOrder|( = runHigherOrder@fun (): R|kotlin/Int| { ^ R|/s|.R|kotlin/String.length| } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot index f396aa30071..47b877c55ac 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.dot @@ -50,61 +50,32 @@ digraph smartcastFromArgument_kt { subgraph cluster_7 { color=blue 14 [label="Enter when branch condition "]; - subgraph cluster_8 { - color=blue - 15 [label="Enter when"]; - 16 [label="Access variable R|/a|"]; - 17 [label="Type operator: (R|/a| as? R|A|)"]; - 18 [label="Variable declaration: lval : R|A?|"]; - subgraph cluster_9 { - color=blue - 19 [label="Enter when branch condition "]; - 20 [label="Const: Null(null)"]; - 21 [label="Operator =="]; - 22 [label="Exit when branch condition"]; - } - subgraph cluster_10 { - color=blue - 23 [label="Enter when branch condition else"]; - 24 [label="Exit when branch condition"]; - } - 25 [label="Enter when branch result"]; - subgraph cluster_11 { - color=blue - 26 [label="Enter block"]; - 27 [label="Access variable R|/|"]; - 28 [label="Exit block"]; - } - 29 [label="Exit when branch result"]; - 30 [label="Enter when branch result"]; - subgraph cluster_12 { - color=blue - 31 [label="Enter block"]; - 32 [label="Jump: ^test Unit"]; - 33 [label="Stub" style="filled" fillcolor=gray]; - 34 [label="Exit block" style="filled" fillcolor=gray]; - } - 35 [label="Exit when branch result" style="filled" fillcolor=gray]; - 36 [label="Exit when"]; - } - 37 [label="Function call: R|/takeA|(...)"]; - 38 [label="Exit when branch condition"]; + 15 [label="Access variable R|/a|"]; + 16 [label="Type operator: (R|/a| as? R|A|)"]; + 17 [label="Exit lhs of ?:"]; + 18 [label="Enter rhs of ?:"]; + 19 [label="Jump: ^test Unit"]; + 20 [label="Stub" style="filled" fillcolor=gray]; + 21 [label="Lhs of ?: is not null"]; + 22 [label="Exit ?:"]; + 23 [label="Function call: R|/takeA|(...)"]; + 24 [label="Exit when branch condition"]; } - 39 [label="Synthetic else branch"]; - 40 [label="Enter when branch result"]; - subgraph cluster_13 { + 25 [label="Synthetic else branch"]; + 26 [label="Enter when branch result"]; + subgraph cluster_8 { color=blue - 41 [label="Enter block"]; - 42 [label="Access variable R|/a|"]; - 43 [label="Function call: R|/a|.R|/A.foo|()"]; - 44 [label="Exit block"]; + 27 [label="Enter block"]; + 28 [label="Access variable R|/a|"]; + 29 [label="Function call: R|/a|.R|/A.foo|()"]; + 30 [label="Exit block"]; } - 45 [label="Exit when branch result"]; - 46 [label="Exit when"]; + 31 [label="Exit when branch result"]; + 32 [label="Exit when"]; } - 47 [label="Exit block"]; + 33 [label="Exit block"]; } - 48 [label="Exit function test" style="filled" fillcolor=red]; + 34 [label="Exit function test" style="filled" fillcolor=red]; } 11 -> {12}; 12 -> {13}; @@ -112,37 +83,23 @@ digraph smartcastFromArgument_kt { 14 -> {15}; 15 -> {16}; 16 -> {17}; - 17 -> {18}; + 17 -> {21 18}; 18 -> {19}; - 19 -> {20}; - 20 -> {21}; + 19 -> {34}; + 19 -> {20} [style=dotted]; + 20 -> {22} [style=dotted]; 21 -> {22}; - 22 -> {30 23}; + 22 -> {23}; 23 -> {24}; - 24 -> {25}; - 25 -> {26}; + 24 -> {26 25}; + 25 -> {32}; 26 -> {27}; 27 -> {28}; 28 -> {29}; - 29 -> {36}; + 29 -> {30}; 30 -> {31}; 31 -> {32}; - 32 -> {48}; - 32 -> {33} [style=dotted]; - 33 -> {34} [style=dotted]; - 34 -> {35} [style=dotted]; - 35 -> {36} [style=dotted]; - 36 -> {37}; - 37 -> {38}; - 38 -> {40 39}; - 39 -> {46}; - 40 -> {41}; - 41 -> {42}; - 42 -> {43}; - 43 -> {44}; - 44 -> {45}; - 45 -> {46}; - 46 -> {47}; - 47 -> {48}; + 32 -> {33}; + 33 -> {34}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt index 3431aafca16..0d517c2d928 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/controlStructures/smartcastFromArgument.txt @@ -8,15 +8,7 @@ FILE: smartcastFromArgument.kt } public final fun test(a: R|kotlin/Any|): R|kotlin/Unit| { when () { - R|/takeA|(when (lval : R|A?| = (R|/a| as? R|A|)) { - ==($subj$, Null(null)) -> { - ^test Unit - } - else -> { - R|/| - } - } - ) -> { + R|/takeA|((R|/a| as? R|A|) ?: ^test Unit) -> { R|/a|.R|/A.foo|() } } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.dot index 15bc6731fc8..bd60e451d01 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.dot @@ -393,319 +393,310 @@ digraph nullability_kt { subgraph cluster_43 { color=blue 128 [label="Enter block"]; - subgraph cluster_44 { - color=blue - 129 [label="Enter when"]; - 130 [label="Access variable R|/x|"]; - 131 [label="Variable declaration: lval : R|A?|"]; - subgraph cluster_45 { - color=blue - 132 [label="Enter when branch condition "]; - 133 [label="Const: Null(null)"]; - 134 [label="Operator =="]; - 135 [label="Exit when branch condition"]; - } - subgraph cluster_46 { - color=blue - 136 [label="Enter when branch condition else"]; - 137 [label="Exit when branch condition"]; - } - 138 [label="Enter when branch result"]; - subgraph cluster_47 { - color=blue - 139 [label="Enter block"]; - 140 [label="Access variable R|/|"]; - 141 [label="Exit block"]; - } - 142 [label="Exit when branch result"]; - 143 [label="Enter when branch result"]; - subgraph cluster_48 { - color=blue - 144 [label="Enter block"]; - 145 [label="Jump: ^test_3 Unit"]; - 146 [label="Stub" style="filled" fillcolor=gray]; - 147 [label="Exit block" style="filled" fillcolor=gray]; - } - 148 [label="Exit when branch result" style="filled" fillcolor=gray]; - 149 [label="Exit when"]; - } - 150 [label="Access variable R|/x|"]; - 151 [label="Function call: R|/x|.R|/A.foo|()"]; - 152 [label="Exit block"]; + 129 [label="Access variable R|/x|"]; + 130 [label="Exit lhs of ?:"]; + 131 [label="Enter rhs of ?:"]; + 132 [label="Jump: ^test_3 Unit"]; + 133 [label="Stub" style="filled" fillcolor=gray]; + 134 [label="Lhs of ?: is not null"]; + 135 [label="Exit ?:"]; + 136 [label="Access variable R|/x|"]; + 137 [label="Function call: R|/x|.R|/A.foo|()"]; + 138 [label="Exit block"]; } - 153 [label="Exit function test_3" style="filled" fillcolor=red]; + 139 [label="Exit function test_3" style="filled" fillcolor=red]; } 127 -> {128}; 128 -> {129}; 129 -> {130}; - 130 -> {131}; + 130 -> {134 131}; 131 -> {132}; - 132 -> {133}; - 133 -> {134}; + 132 -> {139}; + 132 -> {133} [style=dotted]; + 133 -> {135} [style=dotted]; 134 -> {135}; - 135 -> {143 136}; + 135 -> {136}; 136 -> {137}; 137 -> {138}; 138 -> {139}; - 139 -> {140}; + + subgraph cluster_44 { + color=red + 140 [label="Enter function test_4" style="filled" fillcolor=red]; + subgraph cluster_45 { + color=blue + 141 [label="Enter block"]; + subgraph cluster_46 { + color=blue + 142 [label="Enter when"]; + subgraph cluster_47 { + color=blue + 143 [label="Enter when branch condition "]; + 144 [label="Access variable R|/x|"]; + 145 [label="Enter safe call"]; + 146 [label="Function call: $subj$.R|/A.getA|()"]; + 147 [label="Exit safe call"]; + 148 [label="Const: Null(null)"]; + 149 [label="Operator =="]; + 150 [label="Exit when branch condition"]; + } + 151 [label="Synthetic else branch"]; + 152 [label="Enter when branch result"]; + subgraph cluster_48 { + color=blue + 153 [label="Enter block"]; + 154 [label="Jump: ^test_4 Unit"]; + 155 [label="Stub" style="filled" fillcolor=gray]; + 156 [label="Exit block" style="filled" fillcolor=gray]; + } + 157 [label="Exit when branch result" style="filled" fillcolor=gray]; + 158 [label="Exit when"]; + } + 159 [label="Access variable R|/x|"]; + 160 [label="Function call: R|/x|.R|/A.foo|()"]; + 161 [label="Exit block"]; + } + 162 [label="Exit function test_4" style="filled" fillcolor=red]; + } 140 -> {141}; 141 -> {142}; - 142 -> {149}; + 142 -> {143}; 143 -> {144}; - 144 -> {145}; - 145 -> {153}; - 145 -> {146} [style=dotted]; - 146 -> {147} [style=dotted]; - 147 -> {148} [style=dotted]; - 148 -> {149} [style=dotted]; + 144 -> {145 147}; + 145 -> {146}; + 146 -> {147}; + 147 -> {148}; + 148 -> {149}; 149 -> {150}; - 150 -> {151}; - 151 -> {152}; + 150 -> {152 151}; + 151 -> {158}; 152 -> {153}; - - subgraph cluster_49 { - color=red - 154 [label="Enter function test_4" style="filled" fillcolor=red]; - subgraph cluster_50 { - color=blue - 155 [label="Enter block"]; - subgraph cluster_51 { - color=blue - 156 [label="Enter when"]; - subgraph cluster_52 { - color=blue - 157 [label="Enter when branch condition "]; - 158 [label="Access variable R|/x|"]; - 159 [label="Enter safe call"]; - 160 [label="Function call: $subj$.R|/A.getA|()"]; - 161 [label="Exit safe call"]; - 162 [label="Const: Null(null)"]; - 163 [label="Operator =="]; - 164 [label="Exit when branch condition"]; - } - 165 [label="Synthetic else branch"]; - 166 [label="Enter when branch result"]; - subgraph cluster_53 { - color=blue - 167 [label="Enter block"]; - 168 [label="Jump: ^test_4 Unit"]; - 169 [label="Stub" style="filled" fillcolor=gray]; - 170 [label="Exit block" style="filled" fillcolor=gray]; - } - 171 [label="Exit when branch result" style="filled" fillcolor=gray]; - 172 [label="Exit when"]; - } - 173 [label="Access variable R|/x|"]; - 174 [label="Function call: R|/x|.R|/A.foo|()"]; - 175 [label="Exit block"]; - } - 176 [label="Exit function test_4" style="filled" fillcolor=red]; - } - 154 -> {155}; - 155 -> {156}; - 156 -> {157}; - 157 -> {158}; - 158 -> {159 161}; + 153 -> {154}; + 154 -> {162}; + 154 -> {155} [style=dotted]; + 155 -> {156} [style=dotted]; + 156 -> {157} [style=dotted]; + 157 -> {158} [style=dotted]; + 158 -> {159}; 159 -> {160}; 160 -> {161}; 161 -> {162}; - 162 -> {163}; + + subgraph cluster_49 { + color=red + 163 [label="Enter function test_5" style="filled" fillcolor=red]; + subgraph cluster_50 { + color=blue + 164 [label="Enter block"]; + subgraph cluster_51 { + color=blue + 165 [label="Enter when"]; + subgraph cluster_52 { + color=blue + 166 [label="Enter when branch condition "]; + 167 [label="Access variable R|/q|"]; + 168 [label="Enter safe call"]; + 169 [label="Access variable R|/Q.data|"]; + 170 [label="Exit safe call"]; + 171 [label="Enter safe call"]; + 172 [label="Access variable R|/MyData.s|"]; + 173 [label="Exit safe call"]; + 174 [label="Enter safe call"]; + 175 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 176 [label="Exit safe call"]; + 177 [label="Const: Null(null)"]; + 178 [label="Operator !="]; + 179 [label="Exit when branch condition"]; + } + 180 [label="Synthetic else branch"]; + 181 [label="Enter when branch result"]; + subgraph cluster_53 { + color=blue + 182 [label="Enter block"]; + 183 [label="Access variable R|/q|"]; + 184 [label="Access variable R|/Q.data|"]; + 185 [label="Access variable R|/q|"]; + 186 [label="Access variable R|/Q.data|"]; + 187 [label="Access variable #"]; + 188 [label="Access variable R|/q|"]; + 189 [label="Access variable R|/Q.data|"]; + 190 [label="Access variable #"]; + 191 [label="Function call: R|/q|.R|/Q.data|.#.#()"]; + 192 [label="Exit block"]; + } + 193 [label="Exit when branch result"]; + 194 [label="Exit when"]; + } + 195 [label="Exit block"]; + } + 196 [label="Exit function test_5" style="filled" fillcolor=red]; + } 163 -> {164}; - 164 -> {166 165}; - 165 -> {172}; + 164 -> {165}; + 165 -> {166}; 166 -> {167}; - 167 -> {168}; - 168 -> {176}; - 168 -> {169} [style=dotted]; - 169 -> {170} [style=dotted]; - 170 -> {171} [style=dotted]; - 171 -> {172} [style=dotted]; + 167 -> {168 170}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171 173}; + 171 -> {172}; 172 -> {173}; - 173 -> {174}; + 173 -> {174 176}; 174 -> {175}; 175 -> {176}; - - subgraph cluster_54 { - color=red - 177 [label="Enter function test_5" style="filled" fillcolor=red]; - subgraph cluster_55 { - color=blue - 178 [label="Enter block"]; - subgraph cluster_56 { - color=blue - 179 [label="Enter when"]; - subgraph cluster_57 { - color=blue - 180 [label="Enter when branch condition "]; - 181 [label="Access variable R|/q|"]; - 182 [label="Enter safe call"]; - 183 [label="Access variable R|/Q.data|"]; - 184 [label="Exit safe call"]; - 185 [label="Enter safe call"]; - 186 [label="Access variable R|/MyData.s|"]; - 187 [label="Exit safe call"]; - 188 [label="Enter safe call"]; - 189 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 190 [label="Exit safe call"]; - 191 [label="Const: Null(null)"]; - 192 [label="Operator !="]; - 193 [label="Exit when branch condition"]; - } - 194 [label="Synthetic else branch"]; - 195 [label="Enter when branch result"]; - subgraph cluster_58 { - color=blue - 196 [label="Enter block"]; - 197 [label="Access variable R|/q|"]; - 198 [label="Access variable R|/Q.data|"]; - 199 [label="Access variable R|/q|"]; - 200 [label="Access variable R|/Q.data|"]; - 201 [label="Access variable #"]; - 202 [label="Access variable R|/q|"]; - 203 [label="Access variable R|/Q.data|"]; - 204 [label="Access variable #"]; - 205 [label="Function call: R|/q|.R|/Q.data|.#.#()"]; - 206 [label="Exit block"]; - } - 207 [label="Exit when branch result"]; - 208 [label="Exit when"]; - } - 209 [label="Exit block"]; - } - 210 [label="Exit function test_5" style="filled" fillcolor=red]; - } + 176 -> {177}; 177 -> {178}; 178 -> {179}; - 179 -> {180}; - 180 -> {181}; - 181 -> {182 184}; + 179 -> {181 180}; + 180 -> {194}; + 181 -> {182}; 182 -> {183}; 183 -> {184}; - 184 -> {185 187}; + 184 -> {185}; 185 -> {186}; 186 -> {187}; - 187 -> {188 190}; + 187 -> {188}; 188 -> {189}; 189 -> {190}; 190 -> {191}; 191 -> {192}; 192 -> {193}; - 193 -> {195 194}; - 194 -> {208}; + 193 -> {194}; + 194 -> {195}; 195 -> {196}; - 196 -> {197}; + + subgraph cluster_54 { + color=red + 197 [label="Enter function test_6" style="filled" fillcolor=red]; + subgraph cluster_55 { + color=blue + 198 [label="Enter block"]; + 199 [label="Access variable R|/q|"]; + 200 [label="Enter safe call"]; + 201 [label="Access variable R|/Q.data|"]; + 202 [label="Exit safe call"]; + 203 [label="Enter safe call"]; + 204 [label="Access variable R|/MyData.s|"]; + 205 [label="Exit safe call"]; + 206 [label="Enter safe call"]; + 207 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 208 [label="Exit safe call"]; + 209 [label="Exit lhs of ?:"]; + 210 [label="Enter rhs of ?:"]; + 211 [label="Jump: ^test_6 Unit"]; + 212 [label="Stub" style="filled" fillcolor=gray]; + 213 [label="Lhs of ?: is not null"]; + 214 [label="Exit ?:"]; + 215 [label="Access variable R|/q|"]; + 216 [label="Access variable R|/Q.data|"]; + 217 [label="Access variable R|/q|"]; + 218 [label="Access variable R|/Q.data|"]; + 219 [label="Access variable #"]; + 220 [label="Access variable R|/q|"]; + 221 [label="Access variable R|/Q.data|"]; + 222 [label="Access variable #"]; + 223 [label="Function call: R|/q|.R|/Q.data|.#.#()"]; + 224 [label="Exit block"]; + } + 225 [label="Exit function test_6" style="filled" fillcolor=red]; + } 197 -> {198}; 198 -> {199}; - 199 -> {200}; + 199 -> {200 202}; 200 -> {201}; 201 -> {202}; - 202 -> {203}; + 202 -> {203 205}; 203 -> {204}; 204 -> {205}; - 205 -> {206}; + 205 -> {206 208}; 206 -> {207}; 207 -> {208}; 208 -> {209}; - 209 -> {210}; - - subgraph cluster_59 { - color=red - 211 [label="Enter function test_6" style="filled" fillcolor=red]; - subgraph cluster_60 { - color=blue - 212 [label="Enter block"]; - subgraph cluster_61 { - color=blue - 213 [label="Enter when"]; - 214 [label="Access variable R|/q|"]; - 215 [label="Enter safe call"]; - 216 [label="Access variable R|/Q.data|"]; - 217 [label="Exit safe call"]; - 218 [label="Enter safe call"]; - 219 [label="Access variable R|/MyData.s|"]; - 220 [label="Exit safe call"]; - 221 [label="Enter safe call"]; - 222 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 223 [label="Exit safe call"]; - 224 [label="Variable declaration: lval : R|kotlin/Int?|"]; - subgraph cluster_62 { - color=blue - 225 [label="Enter when branch condition "]; - 226 [label="Const: Null(null)"]; - 227 [label="Operator =="]; - 228 [label="Exit when branch condition"]; - } - subgraph cluster_63 { - color=blue - 229 [label="Enter when branch condition else"]; - 230 [label="Exit when branch condition"]; - } - 231 [label="Enter when branch result"]; - subgraph cluster_64 { - color=blue - 232 [label="Enter block"]; - 233 [label="Access variable R|/|"]; - 234 [label="Exit block"]; - } - 235 [label="Exit when branch result"]; - 236 [label="Enter when branch result"]; - subgraph cluster_65 { - color=blue - 237 [label="Enter block"]; - 238 [label="Jump: ^test_6 Unit"]; - 239 [label="Stub" style="filled" fillcolor=gray]; - 240 [label="Exit block" style="filled" fillcolor=gray]; - } - 241 [label="Exit when branch result" style="filled" fillcolor=gray]; - 242 [label="Exit when"]; - } - 243 [label="Access variable R|/q|"]; - 244 [label="Access variable R|/Q.data|"]; - 245 [label="Access variable R|/q|"]; - 246 [label="Access variable R|/Q.data|"]; - 247 [label="Access variable #"]; - 248 [label="Access variable R|/q|"]; - 249 [label="Access variable R|/Q.data|"]; - 250 [label="Access variable #"]; - 251 [label="Function call: R|/q|.R|/Q.data|.#.#()"]; - 252 [label="Exit block"]; - } - 253 [label="Exit function test_6" style="filled" fillcolor=red]; - } - 211 -> {212}; - 212 -> {213}; + 209 -> {213 210}; + 210 -> {211}; + 211 -> {225}; + 211 -> {212} [style=dotted]; + 212 -> {214} [style=dotted]; 213 -> {214}; - 214 -> {215 217}; + 214 -> {215}; 215 -> {216}; 216 -> {217}; - 217 -> {218 220}; + 217 -> {218}; 218 -> {219}; 219 -> {220}; - 220 -> {221 223}; + 220 -> {221}; 221 -> {222}; 222 -> {223}; 223 -> {224}; 224 -> {225}; - 225 -> {226}; + + subgraph cluster_56 { + color=red + 226 [label="Enter function test_7" style="filled" fillcolor=red]; + subgraph cluster_57 { + color=blue + 227 [label="Enter block"]; + subgraph cluster_58 { + color=blue + 228 [label="Enter when"]; + subgraph cluster_59 { + color=blue + 229 [label="Enter when branch condition "]; + 230 [label="Access variable R|/q|"]; + 231 [label="Enter safe call"]; + 232 [label="Function call: $subj$.R|/Q.fdata|()"]; + 233 [label="Exit safe call"]; + 234 [label="Enter safe call"]; + 235 [label="Function call: $subj$.R|/MyData.fs|()"]; + 236 [label="Exit safe call"]; + 237 [label="Enter safe call"]; + 238 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 239 [label="Exit safe call"]; + 240 [label="Const: Null(null)"]; + 241 [label="Operator !="]; + 242 [label="Exit when branch condition"]; + } + 243 [label="Synthetic else branch"]; + 244 [label="Enter when branch result"]; + subgraph cluster_60 { + color=blue + 245 [label="Enter block"]; + 246 [label="Access variable R|/q|"]; + 247 [label="Function call: R|/q|.R|/Q.fdata|()"]; + 248 [label="Access variable R|/q|"]; + 249 [label="Function call: R|/q|.R|/Q.fdata|()"]; + 250 [label="Function call: R|/q|.R|/Q.fdata|().#()"]; + 251 [label="Access variable R|/q|"]; + 252 [label="Function call: R|/q|.R|/Q.fdata|()"]; + 253 [label="Function call: R|/q|.R|/Q.fdata|().#()"]; + 254 [label="Function call: R|/q|.R|/Q.fdata|().#().#()"]; + 255 [label="Exit block"]; + } + 256 [label="Exit when branch result"]; + 257 [label="Exit when"]; + } + 258 [label="Exit block"]; + } + 259 [label="Exit function test_7" style="filled" fillcolor=red]; + } 226 -> {227}; 227 -> {228}; - 228 -> {236 229}; + 228 -> {229}; 229 -> {230}; - 230 -> {231}; + 230 -> {231 233}; 231 -> {232}; 232 -> {233}; - 233 -> {234}; + 233 -> {234 236}; 234 -> {235}; - 235 -> {242}; - 236 -> {237}; + 235 -> {236}; + 236 -> {237 239}; 237 -> {238}; - 238 -> {253}; - 238 -> {239} [style=dotted]; - 239 -> {240} [style=dotted]; - 240 -> {241} [style=dotted]; - 241 -> {242} [style=dotted]; - 242 -> {243}; - 243 -> {244}; + 238 -> {239}; + 239 -> {240}; + 240 -> {241}; + 241 -> {242}; + 242 -> {244 243}; + 243 -> {257}; 244 -> {245}; 245 -> {246}; 246 -> {247}; @@ -715,80 +706,174 @@ digraph nullability_kt { 250 -> {251}; 251 -> {252}; 252 -> {253}; - - subgraph cluster_66 { - color=red - 254 [label="Enter function test_7" style="filled" fillcolor=red]; - subgraph cluster_67 { - color=blue - 255 [label="Enter block"]; - subgraph cluster_68 { - color=blue - 256 [label="Enter when"]; - subgraph cluster_69 { - color=blue - 257 [label="Enter when branch condition "]; - 258 [label="Access variable R|/q|"]; - 259 [label="Enter safe call"]; - 260 [label="Function call: $subj$.R|/Q.fdata|()"]; - 261 [label="Exit safe call"]; - 262 [label="Enter safe call"]; - 263 [label="Function call: $subj$.R|/MyData.fs|()"]; - 264 [label="Exit safe call"]; - 265 [label="Enter safe call"]; - 266 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 267 [label="Exit safe call"]; - 268 [label="Const: Null(null)"]; - 269 [label="Operator !="]; - 270 [label="Exit when branch condition"]; - } - 271 [label="Synthetic else branch"]; - 272 [label="Enter when branch result"]; - subgraph cluster_70 { - color=blue - 273 [label="Enter block"]; - 274 [label="Access variable R|/q|"]; - 275 [label="Function call: R|/q|.R|/Q.fdata|()"]; - 276 [label="Access variable R|/q|"]; - 277 [label="Function call: R|/q|.R|/Q.fdata|()"]; - 278 [label="Function call: R|/q|.R|/Q.fdata|().#()"]; - 279 [label="Access variable R|/q|"]; - 280 [label="Function call: R|/q|.R|/Q.fdata|()"]; - 281 [label="Function call: R|/q|.R|/Q.fdata|().#()"]; - 282 [label="Function call: R|/q|.R|/Q.fdata|().#().#()"]; - 283 [label="Exit block"]; - } - 284 [label="Exit when branch result"]; - 285 [label="Exit when"]; - } - 286 [label="Exit block"]; - } - 287 [label="Exit function test_7" style="filled" fillcolor=red]; - } + 253 -> {254}; 254 -> {255}; 255 -> {256}; 256 -> {257}; 257 -> {258}; - 258 -> {259 261}; - 259 -> {260}; + 258 -> {259}; + + subgraph cluster_61 { + color=red + 260 [label="Enter function test_8" style="filled" fillcolor=red]; + subgraph cluster_62 { + color=blue + 261 [label="Enter block"]; + subgraph cluster_63 { + color=blue + 262 [label="Enter when"]; + subgraph cluster_64 { + color=blue + 263 [label="Enter when branch condition "]; + 264 [label="Access variable R|/b|"]; + 265 [label="Const: Boolean(true)"]; + 266 [label="Operator =="]; + 267 [label="Exit when branch condition"]; + } + 268 [label="Synthetic else branch"]; + 269 [label="Enter when branch result"]; + subgraph cluster_65 { + color=blue + 270 [label="Enter block"]; + 271 [label="Access variable R|/b|"]; + 272 [label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; + 273 [label="Exit block"]; + } + 274 [label="Exit when branch result"]; + 275 [label="Exit when"]; + } + 276 [label="Exit block"]; + } + 277 [label="Exit function test_8" style="filled" fillcolor=red]; + } 260 -> {261}; - 261 -> {262 264}; + 261 -> {262}; 262 -> {263}; 263 -> {264}; - 264 -> {265 267}; + 264 -> {265}; 265 -> {266}; 266 -> {267}; - 267 -> {268}; - 268 -> {269}; + 267 -> {269 268}; + 268 -> {275}; 269 -> {270}; - 270 -> {272 271}; - 271 -> {285}; + 270 -> {271}; + 271 -> {272}; 272 -> {273}; 273 -> {274}; 274 -> {275}; 275 -> {276}; 276 -> {277}; - 277 -> {278}; + + subgraph cluster_66 { + color=red + 278 [label="Enter function test_9" style="filled" fillcolor=red]; + subgraph cluster_67 { + color=blue + 279 [label="Enter block"]; + subgraph cluster_68 { + color=blue + 280 [label="Enter when"]; + subgraph cluster_69 { + color=blue + 281 [label="Enter when branch condition "]; + 282 [label="Access variable R|/a|"]; + 283 [label="Access variable R|/b|"]; + 284 [label="Operator =="]; + 285 [label="Exit when branch condition"]; + } + 286 [label="Synthetic else branch"]; + 287 [label="Enter when branch result"]; + subgraph cluster_70 { + color=blue + 288 [label="Enter block"]; + 289 [label="Access variable R|/b|"]; + 290 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; + 291 [label="Exit block"]; + } + 292 [label="Exit when branch result"]; + 293 [label="Exit when"]; + } + 294 [label="Access variable R|/b|"]; + 295 [label="Function call: R|/b|.#()"]; + subgraph cluster_71 { + color=blue + 296 [label="Enter when"]; + subgraph cluster_72 { + color=blue + 297 [label="Enter when branch condition "]; + 298 [label="Access variable R|/a|"]; + 299 [label="Access variable R|/b|"]; + 300 [label="Operator ==="]; + 301 [label="Exit when branch condition"]; + } + 302 [label="Synthetic else branch"]; + 303 [label="Enter when branch result"]; + subgraph cluster_73 { + color=blue + 304 [label="Enter block"]; + 305 [label="Access variable R|/b|"]; + 306 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; + 307 [label="Exit block"]; + } + 308 [label="Exit when branch result"]; + 309 [label="Exit when"]; + } + 310 [label="Access variable R|/b|"]; + 311 [label="Function call: R|/b|.#()"]; + subgraph cluster_74 { + color=blue + 312 [label="Enter when"]; + subgraph cluster_75 { + color=blue + 313 [label="Enter when branch condition "]; + 314 [label="Access variable R|/b|"]; + 315 [label="Access variable R|/a|"]; + 316 [label="Operator =="]; + 317 [label="Exit when branch condition"]; + } + 318 [label="Synthetic else branch"]; + 319 [label="Enter when branch result"]; + subgraph cluster_76 { + color=blue + 320 [label="Enter block"]; + 321 [label="Access variable R|/b|"]; + 322 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; + 323 [label="Exit block"]; + } + 324 [label="Exit when branch result"]; + 325 [label="Exit when"]; + } + 326 [label="Access variable R|/b|"]; + 327 [label="Function call: R|/b|.#()"]; + subgraph cluster_77 { + color=blue + 328 [label="Enter when"]; + subgraph cluster_78 { + color=blue + 329 [label="Enter when branch condition "]; + 330 [label="Access variable R|/b|"]; + 331 [label="Access variable R|/a|"]; + 332 [label="Operator ==="]; + 333 [label="Exit when branch condition"]; + } + 334 [label="Synthetic else branch"]; + 335 [label="Enter when branch result"]; + subgraph cluster_79 { + color=blue + 336 [label="Enter block"]; + 337 [label="Access variable R|/b|"]; + 338 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; + 339 [label="Exit block"]; + } + 340 [label="Exit when branch result"]; + 341 [label="Exit when"]; + } + 342 [label="Access variable R|/b|"]; + 343 [label="Function call: R|/b|.#()"]; + 344 [label="Exit block"]; + } + 345 [label="Exit function test_9" style="filled" fillcolor=red]; + } 278 -> {279}; 279 -> {280}; 280 -> {281}; @@ -796,42 +881,9 @@ digraph nullability_kt { 282 -> {283}; 283 -> {284}; 284 -> {285}; - 285 -> {286}; - 286 -> {287}; - - subgraph cluster_71 { - color=red - 288 [label="Enter function test_8" style="filled" fillcolor=red]; - subgraph cluster_72 { - color=blue - 289 [label="Enter block"]; - subgraph cluster_73 { - color=blue - 290 [label="Enter when"]; - subgraph cluster_74 { - color=blue - 291 [label="Enter when branch condition "]; - 292 [label="Access variable R|/b|"]; - 293 [label="Const: Boolean(true)"]; - 294 [label="Operator =="]; - 295 [label="Exit when branch condition"]; - } - 296 [label="Synthetic else branch"]; - 297 [label="Enter when branch result"]; - subgraph cluster_75 { - color=blue - 298 [label="Enter block"]; - 299 [label="Access variable R|/b|"]; - 300 [label="Function call: R|/b|.R|kotlin/Boolean.not|()"]; - 301 [label="Exit block"]; - } - 302 [label="Exit when branch result"]; - 303 [label="Exit when"]; - } - 304 [label="Exit block"]; - } - 305 [label="Exit function test_8" style="filled" fillcolor=red]; - } + 285 -> {287 286}; + 286 -> {293}; + 287 -> {288}; 288 -> {289}; 289 -> {290}; 290 -> {291}; @@ -839,127 +891,17 @@ digraph nullability_kt { 292 -> {293}; 293 -> {294}; 294 -> {295}; - 295 -> {297 296}; - 296 -> {303}; + 295 -> {296}; + 296 -> {297}; 297 -> {298}; 298 -> {299}; 299 -> {300}; 300 -> {301}; - 301 -> {302}; - 302 -> {303}; + 301 -> {303 302}; + 302 -> {309}; 303 -> {304}; 304 -> {305}; - - subgraph cluster_76 { - color=red - 306 [label="Enter function test_9" style="filled" fillcolor=red]; - subgraph cluster_77 { - color=blue - 307 [label="Enter block"]; - subgraph cluster_78 { - color=blue - 308 [label="Enter when"]; - subgraph cluster_79 { - color=blue - 309 [label="Enter when branch condition "]; - 310 [label="Access variable R|/a|"]; - 311 [label="Access variable R|/b|"]; - 312 [label="Operator =="]; - 313 [label="Exit when branch condition"]; - } - 314 [label="Synthetic else branch"]; - 315 [label="Enter when branch result"]; - subgraph cluster_80 { - color=blue - 316 [label="Enter block"]; - 317 [label="Access variable R|/b|"]; - 318 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; - 319 [label="Exit block"]; - } - 320 [label="Exit when branch result"]; - 321 [label="Exit when"]; - } - 322 [label="Access variable R|/b|"]; - 323 [label="Function call: R|/b|.#()"]; - subgraph cluster_81 { - color=blue - 324 [label="Enter when"]; - subgraph cluster_82 { - color=blue - 325 [label="Enter when branch condition "]; - 326 [label="Access variable R|/a|"]; - 327 [label="Access variable R|/b|"]; - 328 [label="Operator ==="]; - 329 [label="Exit when branch condition"]; - } - 330 [label="Synthetic else branch"]; - 331 [label="Enter when branch result"]; - subgraph cluster_83 { - color=blue - 332 [label="Enter block"]; - 333 [label="Access variable R|/b|"]; - 334 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; - 335 [label="Exit block"]; - } - 336 [label="Exit when branch result"]; - 337 [label="Exit when"]; - } - 338 [label="Access variable R|/b|"]; - 339 [label="Function call: R|/b|.#()"]; - subgraph cluster_84 { - color=blue - 340 [label="Enter when"]; - subgraph cluster_85 { - color=blue - 341 [label="Enter when branch condition "]; - 342 [label="Access variable R|/b|"]; - 343 [label="Access variable R|/a|"]; - 344 [label="Operator =="]; - 345 [label="Exit when branch condition"]; - } - 346 [label="Synthetic else branch"]; - 347 [label="Enter when branch result"]; - subgraph cluster_86 { - color=blue - 348 [label="Enter block"]; - 349 [label="Access variable R|/b|"]; - 350 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; - 351 [label="Exit block"]; - } - 352 [label="Exit when branch result"]; - 353 [label="Exit when"]; - } - 354 [label="Access variable R|/b|"]; - 355 [label="Function call: R|/b|.#()"]; - subgraph cluster_87 { - color=blue - 356 [label="Enter when"]; - subgraph cluster_88 { - color=blue - 357 [label="Enter when branch condition "]; - 358 [label="Access variable R|/b|"]; - 359 [label="Access variable R|/a|"]; - 360 [label="Operator ==="]; - 361 [label="Exit when branch condition"]; - } - 362 [label="Synthetic else branch"]; - 363 [label="Enter when branch result"]; - subgraph cluster_89 { - color=blue - 364 [label="Enter block"]; - 365 [label="Access variable R|/b|"]; - 366 [label="Function call: R|/b|.R|kotlin/Int.inc|()"]; - 367 [label="Exit block"]; - } - 368 [label="Exit when branch result"]; - 369 [label="Exit when"]; - } - 370 [label="Access variable R|/b|"]; - 371 [label="Function call: R|/b|.#()"]; - 372 [label="Exit block"]; - } - 373 [label="Exit function test_9" style="filled" fillcolor=red]; - } + 305 -> {306}; 306 -> {307}; 307 -> {308}; 308 -> {309}; @@ -967,12 +909,12 @@ digraph nullability_kt { 310 -> {311}; 311 -> {312}; 312 -> {313}; - 313 -> {315 314}; - 314 -> {321}; + 313 -> {314}; + 314 -> {315}; 315 -> {316}; 316 -> {317}; - 317 -> {318}; - 318 -> {319}; + 317 -> {319 318}; + 318 -> {325}; 319 -> {320}; 320 -> {321}; 321 -> {322}; @@ -983,12 +925,12 @@ digraph nullability_kt { 326 -> {327}; 327 -> {328}; 328 -> {329}; - 329 -> {331 330}; - 330 -> {337}; + 329 -> {330}; + 330 -> {331}; 331 -> {332}; 332 -> {333}; - 333 -> {334}; - 334 -> {335}; + 333 -> {335 334}; + 334 -> {341}; 335 -> {336}; 336 -> {337}; 337 -> {338}; @@ -999,145 +941,145 @@ digraph nullability_kt { 342 -> {343}; 343 -> {344}; 344 -> {345}; - 345 -> {347 346}; - 346 -> {353}; + + subgraph cluster_80 { + color=red + 346 [label="Enter function test_10" style="filled" fillcolor=red]; + subgraph cluster_81 { + color=blue + 347 [label="Enter block"]; + subgraph cluster_82 { + color=blue + 348 [label="Enter when"]; + subgraph cluster_83 { + color=blue + 349 [label="Enter when branch condition "]; + 350 [label="Access variable R|/a|"]; + 351 [label="Access variable R|/b|"]; + 352 [label="Operator =="]; + 353 [label="Exit when branch condition"]; + } + 354 [label="Synthetic else branch"]; + 355 [label="Enter when branch result"]; + subgraph cluster_84 { + color=blue + 356 [label="Enter block"]; + 357 [label="Access variable R|/b|"]; + 358 [label="Function call: R|/b|.#()"]; + 359 [label="Exit block"]; + } + 360 [label="Exit when branch result"]; + 361 [label="Exit when"]; + } + 362 [label="Access variable R|/b|"]; + 363 [label="Function call: R|/b|.#()"]; + subgraph cluster_85 { + color=blue + 364 [label="Enter when"]; + subgraph cluster_86 { + color=blue + 365 [label="Enter when branch condition "]; + 366 [label="Access variable R|/a|"]; + 367 [label="Access variable R|/b|"]; + 368 [label="Operator ==="]; + 369 [label="Exit when branch condition"]; + } + 370 [label="Synthetic else branch"]; + 371 [label="Enter when branch result"]; + subgraph cluster_87 { + color=blue + 372 [label="Enter block"]; + 373 [label="Access variable R|/b|"]; + 374 [label="Function call: R|/b|.#()"]; + 375 [label="Exit block"]; + } + 376 [label="Exit when branch result"]; + 377 [label="Exit when"]; + } + 378 [label="Access variable R|/b|"]; + 379 [label="Function call: R|/b|.#()"]; + subgraph cluster_88 { + color=blue + 380 [label="Enter when"]; + subgraph cluster_89 { + color=blue + 381 [label="Enter when branch condition "]; + 382 [label="Access variable R|/b|"]; + 383 [label="Access variable R|/a|"]; + 384 [label="Operator =="]; + 385 [label="Exit when branch condition"]; + } + 386 [label="Synthetic else branch"]; + 387 [label="Enter when branch result"]; + subgraph cluster_90 { + color=blue + 388 [label="Enter block"]; + 389 [label="Access variable R|/b|"]; + 390 [label="Function call: R|/b|.#()"]; + 391 [label="Exit block"]; + } + 392 [label="Exit when branch result"]; + 393 [label="Exit when"]; + } + 394 [label="Access variable R|/b|"]; + 395 [label="Function call: R|/b|.#()"]; + subgraph cluster_91 { + color=blue + 396 [label="Enter when"]; + subgraph cluster_92 { + color=blue + 397 [label="Enter when branch condition "]; + 398 [label="Access variable R|/b|"]; + 399 [label="Access variable R|/a|"]; + 400 [label="Operator ==="]; + 401 [label="Exit when branch condition"]; + } + 402 [label="Synthetic else branch"]; + 403 [label="Enter when branch result"]; + subgraph cluster_93 { + color=blue + 404 [label="Enter block"]; + 405 [label="Access variable R|/b|"]; + 406 [label="Function call: R|/b|.#()"]; + 407 [label="Exit block"]; + } + 408 [label="Exit when branch result"]; + 409 [label="Exit when"]; + } + 410 [label="Access variable R|/b|"]; + 411 [label="Function call: R|/b|.#()"]; + 412 [label="Exit block"]; + } + 413 [label="Exit function test_10" style="filled" fillcolor=red]; + } + 346 -> {347}; 347 -> {348}; 348 -> {349}; 349 -> {350}; 350 -> {351}; 351 -> {352}; 352 -> {353}; - 353 -> {354}; - 354 -> {355}; + 353 -> {355 354}; + 354 -> {361}; 355 -> {356}; 356 -> {357}; 357 -> {358}; 358 -> {359}; 359 -> {360}; 360 -> {361}; - 361 -> {363 362}; - 362 -> {369}; + 361 -> {362}; + 362 -> {363}; 363 -> {364}; 364 -> {365}; 365 -> {366}; 366 -> {367}; 367 -> {368}; 368 -> {369}; - 369 -> {370}; - 370 -> {371}; + 369 -> {371 370}; + 370 -> {377}; 371 -> {372}; 372 -> {373}; - - subgraph cluster_90 { - color=red - 374 [label="Enter function test_10" style="filled" fillcolor=red]; - subgraph cluster_91 { - color=blue - 375 [label="Enter block"]; - subgraph cluster_92 { - color=blue - 376 [label="Enter when"]; - subgraph cluster_93 { - color=blue - 377 [label="Enter when branch condition "]; - 378 [label="Access variable R|/a|"]; - 379 [label="Access variable R|/b|"]; - 380 [label="Operator =="]; - 381 [label="Exit when branch condition"]; - } - 382 [label="Synthetic else branch"]; - 383 [label="Enter when branch result"]; - subgraph cluster_94 { - color=blue - 384 [label="Enter block"]; - 385 [label="Access variable R|/b|"]; - 386 [label="Function call: R|/b|.#()"]; - 387 [label="Exit block"]; - } - 388 [label="Exit when branch result"]; - 389 [label="Exit when"]; - } - 390 [label="Access variable R|/b|"]; - 391 [label="Function call: R|/b|.#()"]; - subgraph cluster_95 { - color=blue - 392 [label="Enter when"]; - subgraph cluster_96 { - color=blue - 393 [label="Enter when branch condition "]; - 394 [label="Access variable R|/a|"]; - 395 [label="Access variable R|/b|"]; - 396 [label="Operator ==="]; - 397 [label="Exit when branch condition"]; - } - 398 [label="Synthetic else branch"]; - 399 [label="Enter when branch result"]; - subgraph cluster_97 { - color=blue - 400 [label="Enter block"]; - 401 [label="Access variable R|/b|"]; - 402 [label="Function call: R|/b|.#()"]; - 403 [label="Exit block"]; - } - 404 [label="Exit when branch result"]; - 405 [label="Exit when"]; - } - 406 [label="Access variable R|/b|"]; - 407 [label="Function call: R|/b|.#()"]; - subgraph cluster_98 { - color=blue - 408 [label="Enter when"]; - subgraph cluster_99 { - color=blue - 409 [label="Enter when branch condition "]; - 410 [label="Access variable R|/b|"]; - 411 [label="Access variable R|/a|"]; - 412 [label="Operator =="]; - 413 [label="Exit when branch condition"]; - } - 414 [label="Synthetic else branch"]; - 415 [label="Enter when branch result"]; - subgraph cluster_100 { - color=blue - 416 [label="Enter block"]; - 417 [label="Access variable R|/b|"]; - 418 [label="Function call: R|/b|.#()"]; - 419 [label="Exit block"]; - } - 420 [label="Exit when branch result"]; - 421 [label="Exit when"]; - } - 422 [label="Access variable R|/b|"]; - 423 [label="Function call: R|/b|.#()"]; - subgraph cluster_101 { - color=blue - 424 [label="Enter when"]; - subgraph cluster_102 { - color=blue - 425 [label="Enter when branch condition "]; - 426 [label="Access variable R|/b|"]; - 427 [label="Access variable R|/a|"]; - 428 [label="Operator ==="]; - 429 [label="Exit when branch condition"]; - } - 430 [label="Synthetic else branch"]; - 431 [label="Enter when branch result"]; - subgraph cluster_103 { - color=blue - 432 [label="Enter block"]; - 433 [label="Access variable R|/b|"]; - 434 [label="Function call: R|/b|.#()"]; - 435 [label="Exit block"]; - } - 436 [label="Exit when branch result"]; - 437 [label="Exit when"]; - } - 438 [label="Access variable R|/b|"]; - 439 [label="Function call: R|/b|.#()"]; - 440 [label="Exit block"]; - } - 441 [label="Exit function test_10" style="filled" fillcolor=red]; - } + 373 -> {374}; 374 -> {375}; 375 -> {376}; 376 -> {377}; @@ -1145,12 +1087,12 @@ digraph nullability_kt { 378 -> {379}; 379 -> {380}; 380 -> {381}; - 381 -> {383 382}; - 382 -> {389}; + 381 -> {382}; + 382 -> {383}; 383 -> {384}; 384 -> {385}; - 385 -> {386}; - 386 -> {387}; + 385 -> {387 386}; + 386 -> {393}; 387 -> {388}; 388 -> {389}; 389 -> {390}; @@ -1161,12 +1103,12 @@ digraph nullability_kt { 394 -> {395}; 395 -> {396}; 396 -> {397}; - 397 -> {399 398}; - 398 -> {405}; + 397 -> {398}; + 398 -> {399}; 399 -> {400}; 400 -> {401}; - 401 -> {402}; - 402 -> {403}; + 401 -> {403 402}; + 402 -> {409}; 403 -> {404}; 404 -> {405}; 405 -> {406}; @@ -1177,25 +1119,112 @@ digraph nullability_kt { 410 -> {411}; 411 -> {412}; 412 -> {413}; - 413 -> {415 414}; - 414 -> {421}; + + subgraph cluster_94 { + color=red + 414 [label="Enter function test_11" style="filled" fillcolor=red]; + subgraph cluster_95 { + color=blue + 415 [label="Enter block"]; + subgraph cluster_96 { + color=blue + 416 [label="Enter when"]; + subgraph cluster_97 { + color=blue + 417 [label="Enter when branch condition "]; + 418 [label="Access variable R|/q|"]; + 419 [label="Enter safe call"]; + 420 [label="Access variable R|/QImpl.data|"]; + 421 [label="Exit safe call"]; + 422 [label="Enter safe call"]; + 423 [label="Access variable R|/MyData.s|"]; + 424 [label="Exit safe call"]; + 425 [label="Enter safe call"]; + 426 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 427 [label="Exit safe call"]; + 428 [label="Const: Null(null)"]; + 429 [label="Operator !="]; + 430 [label="Exit when branch condition"]; + } + 431 [label="Synthetic else branch"]; + 432 [label="Enter when branch result"]; + subgraph cluster_98 { + color=blue + 433 [label="Enter block"]; + 434 [label="Access variable R|/q|"]; + 435 [label="Access variable R|/QImpl.data|"]; + 436 [label="Access variable R|/q|"]; + 437 [label="Access variable R|/QImpl.data|"]; + 438 [label="Access variable R|/MyData.s|"]; + 439 [label="Access variable R|/q|"]; + 440 [label="Access variable R|/QImpl.data|"]; + 441 [label="Access variable R|/MyData.s|"]; + 442 [label="Function call: R|/q|.R|/QImpl.data|.R|/MyData.s|.R|kotlin/Int.inc|()"]; + 443 [label="Access variable R|/q2|"]; + 444 [label="Access variable R|/QImpl.data|"]; + 445 [label="Access variable R|/q2|"]; + 446 [label="Access variable R|/QImpl.data|"]; + 447 [label="Access variable #"]; + 448 [label="Access variable R|/q2|"]; + 449 [label="Access variable R|/QImpl.data|"]; + 450 [label="Access variable #"]; + 451 [label="Function call: R|/q2|.R|/QImpl.data|.#.#()"]; + subgraph cluster_99 { + color=blue + 452 [label="Enter when"]; + subgraph cluster_100 { + color=blue + 453 [label="Enter when branch condition "]; + 454 [label="Access variable R|/q2|"]; + 455 [label="Access variable R|/QImpl.data|"]; + 456 [label="Const: Null(null)"]; + 457 [label="Operator !="]; + 458 [label="Exit when branch condition"]; + } + 459 [label="Synthetic else branch"]; + 460 [label="Enter when branch result"]; + subgraph cluster_101 { + color=blue + 461 [label="Enter block"]; + 462 [label="Access variable R|/q2|"]; + 463 [label="Access variable R|/QImpl.data|"]; + 464 [label="Access variable R|/MyData.s|"]; + 465 [label="Access variable R|/q2|"]; + 466 [label="Access variable R|/QImpl.data|"]; + 467 [label="Access variable R|/MyData.s|"]; + 468 [label="Function call: R|/q2|.R|/QImpl.data|.R|/MyData.s|.R|kotlin/Int.inc|()"]; + 469 [label="Exit block"]; + } + 470 [label="Exit when branch result"]; + 471 [label="Exit when"]; + } + 472 [label="Exit block"]; + } + 473 [label="Exit when branch result"]; + 474 [label="Exit when"]; + } + 475 [label="Exit block"]; + } + 476 [label="Exit function test_11" style="filled" fillcolor=red]; + } + 414 -> {415}; 415 -> {416}; 416 -> {417}; 417 -> {418}; - 418 -> {419}; + 418 -> {419 421}; 419 -> {420}; 420 -> {421}; - 421 -> {422}; + 421 -> {422 424}; 422 -> {423}; 423 -> {424}; - 424 -> {425}; + 424 -> {425 427}; 425 -> {426}; 426 -> {427}; 427 -> {428}; 428 -> {429}; - 429 -> {431 430}; - 430 -> {437}; - 431 -> {432}; + 429 -> {430}; + 430 -> {432 431}; + 431 -> {474}; 432 -> {433}; 433 -> {434}; 434 -> {435}; @@ -1205,112 +1234,25 @@ digraph nullability_kt { 438 -> {439}; 439 -> {440}; 440 -> {441}; - - subgraph cluster_104 { - color=red - 442 [label="Enter function test_11" style="filled" fillcolor=red]; - subgraph cluster_105 { - color=blue - 443 [label="Enter block"]; - subgraph cluster_106 { - color=blue - 444 [label="Enter when"]; - subgraph cluster_107 { - color=blue - 445 [label="Enter when branch condition "]; - 446 [label="Access variable R|/q|"]; - 447 [label="Enter safe call"]; - 448 [label="Access variable R|/QImpl.data|"]; - 449 [label="Exit safe call"]; - 450 [label="Enter safe call"]; - 451 [label="Access variable R|/MyData.s|"]; - 452 [label="Exit safe call"]; - 453 [label="Enter safe call"]; - 454 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 455 [label="Exit safe call"]; - 456 [label="Const: Null(null)"]; - 457 [label="Operator !="]; - 458 [label="Exit when branch condition"]; - } - 459 [label="Synthetic else branch"]; - 460 [label="Enter when branch result"]; - subgraph cluster_108 { - color=blue - 461 [label="Enter block"]; - 462 [label="Access variable R|/q|"]; - 463 [label="Access variable R|/QImpl.data|"]; - 464 [label="Access variable R|/q|"]; - 465 [label="Access variable R|/QImpl.data|"]; - 466 [label="Access variable R|/MyData.s|"]; - 467 [label="Access variable R|/q|"]; - 468 [label="Access variable R|/QImpl.data|"]; - 469 [label="Access variable R|/MyData.s|"]; - 470 [label="Function call: R|/q|.R|/QImpl.data|.R|/MyData.s|.R|kotlin/Int.inc|()"]; - 471 [label="Access variable R|/q2|"]; - 472 [label="Access variable R|/QImpl.data|"]; - 473 [label="Access variable R|/q2|"]; - 474 [label="Access variable R|/QImpl.data|"]; - 475 [label="Access variable #"]; - 476 [label="Access variable R|/q2|"]; - 477 [label="Access variable R|/QImpl.data|"]; - 478 [label="Access variable #"]; - 479 [label="Function call: R|/q2|.R|/QImpl.data|.#.#()"]; - subgraph cluster_109 { - color=blue - 480 [label="Enter when"]; - subgraph cluster_110 { - color=blue - 481 [label="Enter when branch condition "]; - 482 [label="Access variable R|/q2|"]; - 483 [label="Access variable R|/QImpl.data|"]; - 484 [label="Const: Null(null)"]; - 485 [label="Operator !="]; - 486 [label="Exit when branch condition"]; - } - 487 [label="Synthetic else branch"]; - 488 [label="Enter when branch result"]; - subgraph cluster_111 { - color=blue - 489 [label="Enter block"]; - 490 [label="Access variable R|/q2|"]; - 491 [label="Access variable R|/QImpl.data|"]; - 492 [label="Access variable R|/MyData.s|"]; - 493 [label="Access variable R|/q2|"]; - 494 [label="Access variable R|/QImpl.data|"]; - 495 [label="Access variable R|/MyData.s|"]; - 496 [label="Function call: R|/q2|.R|/QImpl.data|.R|/MyData.s|.R|kotlin/Int.inc|()"]; - 497 [label="Exit block"]; - } - 498 [label="Exit when branch result"]; - 499 [label="Exit when"]; - } - 500 [label="Exit block"]; - } - 501 [label="Exit when branch result"]; - 502 [label="Exit when"]; - } - 503 [label="Exit block"]; - } - 504 [label="Exit function test_11" style="filled" fillcolor=red]; - } + 441 -> {442}; 442 -> {443}; 443 -> {444}; 444 -> {445}; 445 -> {446}; - 446 -> {447 449}; + 446 -> {447}; 447 -> {448}; 448 -> {449}; - 449 -> {450 452}; + 449 -> {450}; 450 -> {451}; 451 -> {452}; - 452 -> {453 455}; + 452 -> {453}; 453 -> {454}; 454 -> {455}; 455 -> {456}; 456 -> {457}; 457 -> {458}; 458 -> {460 459}; - 459 -> {502}; + 459 -> {471}; 460 -> {461}; 461 -> {462}; 462 -> {463}; @@ -1327,25 +1269,74 @@ digraph nullability_kt { 473 -> {474}; 474 -> {475}; 475 -> {476}; - 476 -> {477}; + + subgraph cluster_102 { + color=red + 477 [label="Enter function test_12" style="filled" fillcolor=red]; + subgraph cluster_103 { + color=blue + 478 [label="Enter block"]; + subgraph cluster_104 { + color=blue + 479 [label="Enter when"]; + subgraph cluster_105 { + color=blue + 480 [label="Enter when branch condition "]; + 481 [label="Access variable R|/q|"]; + 482 [label="Enter safe call"]; + 483 [label="Access variable R|/QImplWithCustomGetter.data|"]; + 484 [label="Exit safe call"]; + 485 [label="Enter safe call"]; + 486 [label="Access variable R|/MyData.s|"]; + 487 [label="Exit safe call"]; + 488 [label="Enter safe call"]; + 489 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 490 [label="Exit safe call"]; + 491 [label="Const: Null(null)"]; + 492 [label="Operator !="]; + 493 [label="Exit when branch condition"]; + } + 494 [label="Synthetic else branch"]; + 495 [label="Enter when branch result"]; + subgraph cluster_106 { + color=blue + 496 [label="Enter block"]; + 497 [label="Access variable R|/q|"]; + 498 [label="Access variable R|/QImplWithCustomGetter.data|"]; + 499 [label="Access variable R|/q|"]; + 500 [label="Access variable R|/QImplWithCustomGetter.data|"]; + 501 [label="Access variable #"]; + 502 [label="Access variable R|/q|"]; + 503 [label="Access variable R|/QImplWithCustomGetter.data|"]; + 504 [label="Access variable #"]; + 505 [label="Function call: R|/q|.R|/QImplWithCustomGetter.data|.#.#()"]; + 506 [label="Exit block"]; + } + 507 [label="Exit when branch result"]; + 508 [label="Exit when"]; + } + 509 [label="Exit block"]; + } + 510 [label="Exit function test_12" style="filled" fillcolor=red]; + } 477 -> {478}; 478 -> {479}; 479 -> {480}; 480 -> {481}; - 481 -> {482}; + 481 -> {482 484}; 482 -> {483}; 483 -> {484}; - 484 -> {485}; + 484 -> {485 487}; 485 -> {486}; - 486 -> {488 487}; - 487 -> {499}; + 486 -> {487}; + 487 -> {488 490}; 488 -> {489}; 489 -> {490}; 490 -> {491}; 491 -> {492}; 492 -> {493}; - 493 -> {494}; - 494 -> {495}; + 493 -> {495 494}; + 494 -> {508}; 495 -> {496}; 496 -> {497}; 497 -> {498}; @@ -1355,80 +1346,80 @@ digraph nullability_kt { 501 -> {502}; 502 -> {503}; 503 -> {504}; - - subgraph cluster_112 { - color=red - 505 [label="Enter function test_12" style="filled" fillcolor=red]; - subgraph cluster_113 { - color=blue - 506 [label="Enter block"]; - subgraph cluster_114 { - color=blue - 507 [label="Enter when"]; - subgraph cluster_115 { - color=blue - 508 [label="Enter when branch condition "]; - 509 [label="Access variable R|/q|"]; - 510 [label="Enter safe call"]; - 511 [label="Access variable R|/QImplWithCustomGetter.data|"]; - 512 [label="Exit safe call"]; - 513 [label="Enter safe call"]; - 514 [label="Access variable R|/MyData.s|"]; - 515 [label="Exit safe call"]; - 516 [label="Enter safe call"]; - 517 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 518 [label="Exit safe call"]; - 519 [label="Const: Null(null)"]; - 520 [label="Operator !="]; - 521 [label="Exit when branch condition"]; - } - 522 [label="Synthetic else branch"]; - 523 [label="Enter when branch result"]; - subgraph cluster_116 { - color=blue - 524 [label="Enter block"]; - 525 [label="Access variable R|/q|"]; - 526 [label="Access variable R|/QImplWithCustomGetter.data|"]; - 527 [label="Access variable R|/q|"]; - 528 [label="Access variable R|/QImplWithCustomGetter.data|"]; - 529 [label="Access variable #"]; - 530 [label="Access variable R|/q|"]; - 531 [label="Access variable R|/QImplWithCustomGetter.data|"]; - 532 [label="Access variable #"]; - 533 [label="Function call: R|/q|.R|/QImplWithCustomGetter.data|.#.#()"]; - 534 [label="Exit block"]; - } - 535 [label="Exit when branch result"]; - 536 [label="Exit when"]; - } - 537 [label="Exit block"]; - } - 538 [label="Exit function test_12" style="filled" fillcolor=red]; - } + 504 -> {505}; 505 -> {506}; 506 -> {507}; 507 -> {508}; 508 -> {509}; - 509 -> {510 512}; - 510 -> {511}; + 509 -> {510}; + + subgraph cluster_107 { + color=red + 511 [label="Enter function test_13" style="filled" fillcolor=red]; + subgraph cluster_108 { + color=blue + 512 [label="Enter block"]; + subgraph cluster_109 { + color=blue + 513 [label="Enter when"]; + subgraph cluster_110 { + color=blue + 514 [label="Enter when branch condition "]; + 515 [label="Access variable R|/q|"]; + 516 [label="Enter safe call"]; + 517 [label="Access variable R|/QImplMutable.data|"]; + 518 [label="Exit safe call"]; + 519 [label="Enter safe call"]; + 520 [label="Access variable R|/MyData.s|"]; + 521 [label="Exit safe call"]; + 522 [label="Enter safe call"]; + 523 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; + 524 [label="Exit safe call"]; + 525 [label="Const: Null(null)"]; + 526 [label="Operator !="]; + 527 [label="Exit when branch condition"]; + } + 528 [label="Synthetic else branch"]; + 529 [label="Enter when branch result"]; + subgraph cluster_111 { + color=blue + 530 [label="Enter block"]; + 531 [label="Access variable R|/q|"]; + 532 [label="Access variable R|/QImplMutable.data|"]; + 533 [label="Access variable R|/q|"]; + 534 [label="Access variable R|/QImplMutable.data|"]; + 535 [label="Access variable #"]; + 536 [label="Access variable R|/q|"]; + 537 [label="Access variable R|/QImplMutable.data|"]; + 538 [label="Access variable #"]; + 539 [label="Function call: R|/q|.R|/QImplMutable.data|.#.#()"]; + 540 [label="Exit block"]; + } + 541 [label="Exit when branch result"]; + 542 [label="Exit when"]; + } + 543 [label="Exit block"]; + } + 544 [label="Exit function test_13" style="filled" fillcolor=red]; + } 511 -> {512}; - 512 -> {513 515}; + 512 -> {513}; 513 -> {514}; 514 -> {515}; 515 -> {516 518}; 516 -> {517}; 517 -> {518}; - 518 -> {519}; + 518 -> {519 521}; 519 -> {520}; 520 -> {521}; - 521 -> {523 522}; - 522 -> {536}; + 521 -> {522 524}; + 522 -> {523}; 523 -> {524}; 524 -> {525}; 525 -> {526}; 526 -> {527}; - 527 -> {528}; - 528 -> {529}; + 527 -> {529 528}; + 528 -> {542}; 529 -> {530}; 530 -> {531}; 531 -> {532}; @@ -1438,88 +1429,11 @@ digraph nullability_kt { 535 -> {536}; 536 -> {537}; 537 -> {538}; - - subgraph cluster_117 { - color=red - 539 [label="Enter function test_13" style="filled" fillcolor=red]; - subgraph cluster_118 { - color=blue - 540 [label="Enter block"]; - subgraph cluster_119 { - color=blue - 541 [label="Enter when"]; - subgraph cluster_120 { - color=blue - 542 [label="Enter when branch condition "]; - 543 [label="Access variable R|/q|"]; - 544 [label="Enter safe call"]; - 545 [label="Access variable R|/QImplMutable.data|"]; - 546 [label="Exit safe call"]; - 547 [label="Enter safe call"]; - 548 [label="Access variable R|/MyData.s|"]; - 549 [label="Exit safe call"]; - 550 [label="Enter safe call"]; - 551 [label="Function call: $subj$.R|kotlin/Int.inc|()"]; - 552 [label="Exit safe call"]; - 553 [label="Const: Null(null)"]; - 554 [label="Operator !="]; - 555 [label="Exit when branch condition"]; - } - 556 [label="Synthetic else branch"]; - 557 [label="Enter when branch result"]; - subgraph cluster_121 { - color=blue - 558 [label="Enter block"]; - 559 [label="Access variable R|/q|"]; - 560 [label="Access variable R|/QImplMutable.data|"]; - 561 [label="Access variable R|/q|"]; - 562 [label="Access variable R|/QImplMutable.data|"]; - 563 [label="Access variable #"]; - 564 [label="Access variable R|/q|"]; - 565 [label="Access variable R|/QImplMutable.data|"]; - 566 [label="Access variable #"]; - 567 [label="Function call: R|/q|.R|/QImplMutable.data|.#.#()"]; - 568 [label="Exit block"]; - } - 569 [label="Exit when branch result"]; - 570 [label="Exit when"]; - } - 571 [label="Exit block"]; - } - 572 [label="Exit function test_13" style="filled" fillcolor=red]; - } + 538 -> {539}; 539 -> {540}; 540 -> {541}; 541 -> {542}; 542 -> {543}; - 543 -> {544 546}; - 544 -> {545}; - 545 -> {546}; - 546 -> {547 549}; - 547 -> {548}; - 548 -> {549}; - 549 -> {550 552}; - 550 -> {551}; - 551 -> {552}; - 552 -> {553}; - 553 -> {554}; - 554 -> {555}; - 555 -> {557 556}; - 556 -> {570}; - 557 -> {558}; - 558 -> {559}; - 559 -> {560}; - 560 -> {561}; - 561 -> {562}; - 562 -> {563}; - 563 -> {564}; - 564 -> {565}; - 565 -> {566}; - 566 -> {567}; - 567 -> {568}; - 568 -> {569}; - 569 -> {570}; - 570 -> {571}; - 571 -> {572}; + 543 -> {544}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.txt index 5ffac85e437..0f2025d36fb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/nullability.txt @@ -86,15 +86,7 @@ FILE: nullability.kt R|/x|.#() } public final fun test_3(x: R|A?|): R|kotlin/Unit| { - when (lval : R|A?| = R|/x|) { - ==($subj$, Null(null)) -> { - ^test_3 Unit - } - else -> { - R|/| - } - } - + R|/x| ?: ^test_3 Unit R|/x|.R|/A.foo|() } public final fun test_4(x: R|A?|): R|kotlin/Unit| { @@ -117,15 +109,7 @@ FILE: nullability.kt } public final fun test_6(q: R|Q?|): R|kotlin/Unit| { - when (lval : R|kotlin/Int?| = R|/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }) { - ==($subj$, Null(null)) -> { - ^test_6 Unit - } - else -> { - R|/| - } - } - + R|/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() } ?: ^test_6 Unit R|/q|.R|/Q.data| R|/q|.R|/Q.data|.# R|/q|.R|/Q.data|.#.#() diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot index 120d51090a2..cf9e34bfdb5 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.dot @@ -198,164 +198,173 @@ digraph assignSafeCall_kt { subgraph cluster_19 { color=blue 68 [label="Enter block"]; - subgraph cluster_20 { - color=blue - 69 [label="Enter when"]; - 70 [label="Access variable R|/x|"]; - 71 [label="Type operator: (R|/x| as? R|A|)"]; - 72 [label="Variable declaration: lval : R|A?|"]; - subgraph cluster_21 { - color=blue - 73 [label="Enter when branch condition "]; - 74 [label="Const: Null(null)"]; - 75 [label="Operator =="]; - 76 [label="Exit when branch condition"]; - } - subgraph cluster_22 { - color=blue - 77 [label="Enter when branch condition else"]; - 78 [label="Exit when branch condition"]; - } - 79 [label="Enter when branch result"]; - subgraph cluster_23 { - color=blue - 80 [label="Enter block"]; - 81 [label="Access variable R|/|"]; - 82 [label="Exit block"]; - } - 83 [label="Exit when branch result"]; - 84 [label="Enter when branch result"]; - subgraph cluster_24 { - color=blue - 85 [label="Enter block"]; - 86 [label="Jump: ^test_3 Unit"]; - 87 [label="Stub" style="filled" fillcolor=gray]; - 88 [label="Exit block" style="filled" fillcolor=gray]; - } - 89 [label="Exit when branch result" style="filled" fillcolor=gray]; - 90 [label="Exit when"]; - } - 91 [label="Variable declaration: lval a: R|A|"]; - 92 [label="Access variable R|/a|"]; - 93 [label="Function call: R|/a|.R|/A.foo|()"]; - 94 [label="Access variable R|/x|"]; - 95 [label="Function call: R|/x|.R|/A.foo|()"]; - 96 [label="Exit block"]; + 69 [label="Access variable R|/x|"]; + 70 [label="Type operator: (R|/x| as? R|A|)"]; + 71 [label="Exit lhs of ?:"]; + 72 [label="Enter rhs of ?:"]; + 73 [label="Jump: ^test_3 Unit"]; + 74 [label="Stub" style="filled" fillcolor=gray]; + 75 [label="Lhs of ?: is not null"]; + 76 [label="Exit ?:"]; + 77 [label="Variable declaration: lval a: R|A|"]; + 78 [label="Access variable R|/a|"]; + 79 [label="Function call: R|/a|.R|/A.foo|()"]; + 80 [label="Access variable R|/x|"]; + 81 [label="Function call: R|/x|.R|/A.foo|()"]; + 82 [label="Exit block"]; } - 97 [label="Exit function test_3" style="filled" fillcolor=red]; + 83 [label="Exit function test_3" style="filled" fillcolor=red]; } 67 -> {68}; 68 -> {69}; 69 -> {70}; 70 -> {71}; - 71 -> {72}; + 71 -> {75 72}; 72 -> {73}; - 73 -> {74}; - 74 -> {75}; + 73 -> {83}; + 73 -> {74} [style=dotted]; + 74 -> {76} [style=dotted]; 75 -> {76}; - 76 -> {84 77}; + 76 -> {77}; 77 -> {78}; 78 -> {79}; 79 -> {80}; 80 -> {81}; 81 -> {82}; 82 -> {83}; - 83 -> {90}; - 84 -> {85}; - 85 -> {86}; - 86 -> {97}; - 86 -> {87} [style=dotted]; - 87 -> {88} [style=dotted]; - 88 -> {89} [style=dotted]; - 89 -> {90} [style=dotted]; + + subgraph cluster_20 { + color=red + 84 [label="Enter class B" style="filled" fillcolor=red]; + 85 [label="Exit class B" style="filled" fillcolor=red]; + } + 84 -> {85} [color=green]; + + subgraph cluster_21 { + color=red + 86 [label="Enter function foo" style="filled" fillcolor=red]; + 87 [label="Exit function foo" style="filled" fillcolor=red]; + } + 86 -> {87}; + + subgraph cluster_22 { + color=red + 88 [label="Enter function getter" style="filled" fillcolor=red]; + 89 [label="Exit function getter" style="filled" fillcolor=red]; + } + 88 -> {89}; + + subgraph cluster_23 { + color=red + 90 [label="Enter function bar" style="filled" fillcolor=red]; + 91 [label="Exit function bar" style="filled" fillcolor=red]; + } 90 -> {91}; - 91 -> {92}; + + subgraph cluster_24 { + color=red + 92 [label="Enter function test_1" style="filled" fillcolor=red]; + subgraph cluster_25 { + color=blue + 93 [label="Enter block"]; + 94 [label="Access variable R|/a|"]; + 95 [label="Enter safe call"]; + 96 [label="Access variable R|/B.x|"]; + 97 [label="Exit safe call"]; + 98 [label="Variable declaration: lval x: R|kotlin/Int?|"]; + subgraph cluster_26 { + color=blue + 99 [label="Enter when"]; + subgraph cluster_27 { + color=blue + 100 [label="Enter when branch condition "]; + 101 [label="Access variable R|/x|"]; + 102 [label="Const: Null(null)"]; + 103 [label="Operator !="]; + 104 [label="Exit when branch condition"]; + } + 105 [label="Synthetic else branch"]; + 106 [label="Enter when branch result"]; + subgraph cluster_28 { + color=blue + 107 [label="Enter block"]; + 108 [label="Access variable R|/a|"]; + 109 [label="Function call: R|/a|.R|/B.bar|()"]; + 110 [label="Exit block"]; + } + 111 [label="Exit when branch result"]; + 112 [label="Exit when"]; + } + 113 [label="Exit block"]; + } + 114 [label="Exit function test_1" style="filled" fillcolor=red]; + } 92 -> {93}; 93 -> {94}; - 94 -> {95}; + 94 -> {95 97}; 95 -> {96}; 96 -> {97}; - - subgraph cluster_25 { - color=red - 98 [label="Enter class B" style="filled" fillcolor=red]; - 99 [label="Exit class B" style="filled" fillcolor=red]; - } - 98 -> {99} [color=green]; - - subgraph cluster_26 { - color=red - 100 [label="Enter function foo" style="filled" fillcolor=red]; - 101 [label="Exit function foo" style="filled" fillcolor=red]; - } + 97 -> {98}; + 98 -> {99}; + 99 -> {100}; 100 -> {101}; - - subgraph cluster_27 { - color=red - 102 [label="Enter function getter" style="filled" fillcolor=red]; - 103 [label="Exit function getter" style="filled" fillcolor=red]; - } + 101 -> {102}; 102 -> {103}; - - subgraph cluster_28 { - color=red - 104 [label="Enter function bar" style="filled" fillcolor=red]; - 105 [label="Exit function bar" style="filled" fillcolor=red]; - } - 104 -> {105}; - - subgraph cluster_29 { - color=red - 106 [label="Enter function test_1" style="filled" fillcolor=red]; - subgraph cluster_30 { - color=blue - 107 [label="Enter block"]; - 108 [label="Access variable R|/a|"]; - 109 [label="Enter safe call"]; - 110 [label="Access variable R|/B.x|"]; - 111 [label="Exit safe call"]; - 112 [label="Variable declaration: lval x: R|kotlin/Int?|"]; - subgraph cluster_31 { - color=blue - 113 [label="Enter when"]; - subgraph cluster_32 { - color=blue - 114 [label="Enter when branch condition "]; - 115 [label="Access variable R|/x|"]; - 116 [label="Const: Null(null)"]; - 117 [label="Operator !="]; - 118 [label="Exit when branch condition"]; - } - 119 [label="Synthetic else branch"]; - 120 [label="Enter when branch result"]; - subgraph cluster_33 { - color=blue - 121 [label="Enter block"]; - 122 [label="Access variable R|/a|"]; - 123 [label="Function call: R|/a|.R|/B.bar|()"]; - 124 [label="Exit block"]; - } - 125 [label="Exit when branch result"]; - 126 [label="Exit when"]; - } - 127 [label="Exit block"]; - } - 128 [label="Exit function test_1" style="filled" fillcolor=red]; - } + 103 -> {104}; + 104 -> {106 105}; + 105 -> {112}; 106 -> {107}; 107 -> {108}; - 108 -> {109 111}; + 108 -> {109}; 109 -> {110}; 110 -> {111}; 111 -> {112}; 112 -> {113}; 113 -> {114}; - 114 -> {115}; + + subgraph cluster_29 { + color=red + 115 [label="Enter function test_2" style="filled" fillcolor=red]; + subgraph cluster_30 { + color=blue + 116 [label="Enter block"]; + 117 [label="Access variable R|/a|"]; + 118 [label="Enter safe call"]; + 119 [label="Function call: $subj$.R|/B.foo|()"]; + 120 [label="Exit safe call"]; + 121 [label="Variable declaration: lval x: R|kotlin/Int?|"]; + subgraph cluster_31 { + color=blue + 122 [label="Enter when"]; + subgraph cluster_32 { + color=blue + 123 [label="Enter when branch condition "]; + 124 [label="Access variable R|/x|"]; + 125 [label="Const: Null(null)"]; + 126 [label="Operator !="]; + 127 [label="Exit when branch condition"]; + } + 128 [label="Synthetic else branch"]; + 129 [label="Enter when branch result"]; + subgraph cluster_33 { + color=blue + 130 [label="Enter block"]; + 131 [label="Access variable R|/a|"]; + 132 [label="Function call: R|/a|.R|/B.bar|()"]; + 133 [label="Exit block"]; + } + 134 [label="Exit when branch result"]; + 135 [label="Exit when"]; + } + 136 [label="Exit block"]; + } + 137 [label="Exit function test_2" style="filled" fillcolor=red]; + } 115 -> {116}; 116 -> {117}; - 117 -> {118}; - 118 -> {120 119}; - 119 -> {126}; + 117 -> {118 120}; + 118 -> {119}; + 119 -> {120}; 120 -> {121}; 121 -> {122}; 122 -> {123}; @@ -363,151 +372,56 @@ digraph assignSafeCall_kt { 124 -> {125}; 125 -> {126}; 126 -> {127}; - 127 -> {128}; - - subgraph cluster_34 { - color=red - 129 [label="Enter function test_2" style="filled" fillcolor=red]; - subgraph cluster_35 { - color=blue - 130 [label="Enter block"]; - 131 [label="Access variable R|/a|"]; - 132 [label="Enter safe call"]; - 133 [label="Function call: $subj$.R|/B.foo|()"]; - 134 [label="Exit safe call"]; - 135 [label="Variable declaration: lval x: R|kotlin/Int?|"]; - subgraph cluster_36 { - color=blue - 136 [label="Enter when"]; - subgraph cluster_37 { - color=blue - 137 [label="Enter when branch condition "]; - 138 [label="Access variable R|/x|"]; - 139 [label="Const: Null(null)"]; - 140 [label="Operator !="]; - 141 [label="Exit when branch condition"]; - } - 142 [label="Synthetic else branch"]; - 143 [label="Enter when branch result"]; - subgraph cluster_38 { - color=blue - 144 [label="Enter block"]; - 145 [label="Access variable R|/a|"]; - 146 [label="Function call: R|/a|.R|/B.bar|()"]; - 147 [label="Exit block"]; - } - 148 [label="Exit when branch result"]; - 149 [label="Exit when"]; - } - 150 [label="Exit block"]; - } - 151 [label="Exit function test_2" style="filled" fillcolor=red]; - } + 127 -> {129 128}; + 128 -> {135}; 129 -> {130}; 130 -> {131}; - 131 -> {132 134}; + 131 -> {132}; 132 -> {133}; 133 -> {134}; 134 -> {135}; 135 -> {136}; 136 -> {137}; - 137 -> {138}; + + subgraph cluster_34 { + color=red + 138 [label="Enter function test_3" style="filled" fillcolor=red]; + subgraph cluster_35 { + color=blue + 139 [label="Enter block"]; + 140 [label="Access variable R|/x|"]; + 141 [label="Type operator: (R|/x| as? R|B|)"]; + 142 [label="Exit lhs of ?:"]; + 143 [label="Enter rhs of ?:"]; + 144 [label="Jump: ^test_3 Unit"]; + 145 [label="Stub" style="filled" fillcolor=gray]; + 146 [label="Lhs of ?: is not null"]; + 147 [label="Exit ?:"]; + 148 [label="Variable declaration: lval a: R|B|"]; + 149 [label="Access variable R|/a|"]; + 150 [label="Function call: R|/a|.R|/B.foo|()"]; + 151 [label="Access variable R|/x|"]; + 152 [label="Function call: R|/x|.R|/B.foo|()"]; + 153 [label="Exit block"]; + } + 154 [label="Exit function test_3" style="filled" fillcolor=red]; + } 138 -> {139}; 139 -> {140}; 140 -> {141}; - 141 -> {143 142}; - 142 -> {149}; + 141 -> {142}; + 142 -> {146 143}; 143 -> {144}; - 144 -> {145}; - 145 -> {146}; + 144 -> {154}; + 144 -> {145} [style=dotted]; + 145 -> {147} [style=dotted]; 146 -> {147}; 147 -> {148}; 148 -> {149}; 149 -> {150}; 150 -> {151}; - - subgraph cluster_39 { - color=red - 152 [label="Enter function test_3" style="filled" fillcolor=red]; - subgraph cluster_40 { - color=blue - 153 [label="Enter block"]; - subgraph cluster_41 { - color=blue - 154 [label="Enter when"]; - 155 [label="Access variable R|/x|"]; - 156 [label="Type operator: (R|/x| as? R|B|)"]; - 157 [label="Variable declaration: lval : R|B?|"]; - subgraph cluster_42 { - color=blue - 158 [label="Enter when branch condition "]; - 159 [label="Const: Null(null)"]; - 160 [label="Operator =="]; - 161 [label="Exit when branch condition"]; - } - subgraph cluster_43 { - color=blue - 162 [label="Enter when branch condition else"]; - 163 [label="Exit when branch condition"]; - } - 164 [label="Enter when branch result"]; - subgraph cluster_44 { - color=blue - 165 [label="Enter block"]; - 166 [label="Access variable R|/|"]; - 167 [label="Exit block"]; - } - 168 [label="Exit when branch result"]; - 169 [label="Enter when branch result"]; - subgraph cluster_45 { - color=blue - 170 [label="Enter block"]; - 171 [label="Jump: ^test_3 Unit"]; - 172 [label="Stub" style="filled" fillcolor=gray]; - 173 [label="Exit block" style="filled" fillcolor=gray]; - } - 174 [label="Exit when branch result" style="filled" fillcolor=gray]; - 175 [label="Exit when"]; - } - 176 [label="Variable declaration: lval a: R|B|"]; - 177 [label="Access variable R|/a|"]; - 178 [label="Function call: R|/a|.R|/B.foo|()"]; - 179 [label="Access variable R|/x|"]; - 180 [label="Function call: R|/x|.R|/B.foo|()"]; - 181 [label="Exit block"]; - } - 182 [label="Exit function test_3" style="filled" fillcolor=red]; - } + 151 -> {152}; 152 -> {153}; 153 -> {154}; - 154 -> {155}; - 155 -> {156}; - 156 -> {157}; - 157 -> {158}; - 158 -> {159}; - 159 -> {160}; - 160 -> {161}; - 161 -> {169 162}; - 162 -> {163}; - 163 -> {164}; - 164 -> {165}; - 165 -> {166}; - 166 -> {167}; - 167 -> {168}; - 168 -> {175}; - 169 -> {170}; - 170 -> {171}; - 171 -> {182}; - 171 -> {172} [style=dotted]; - 172 -> {173} [style=dotted]; - 173 -> {174} [style=dotted]; - 174 -> {175} [style=dotted]; - 175 -> {176}; - 176 -> {177}; - 177 -> {178}; - 178 -> {179}; - 179 -> {180}; - 180 -> {181}; - 181 -> {182}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt index e148b9ffc44..d65853af936 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.txt @@ -34,15 +34,7 @@ FILE: assignSafeCall.kt } public final fun test_3(x: R|kotlin/Any?|): R|kotlin/Unit| { - lval a: R|A| = when (lval : R|A?| = (R|/x| as? R|A|)) { - ==($subj$, Null(null)) -> { - ^test_3 Unit - } - else -> { - R|/| - } - } - + lval a: R|A| = (R|/x| as? R|A|) ?: ^test_3 Unit R|/a|.R|/A.foo|() R|/x|.R|/A.foo|() } @@ -74,15 +66,7 @@ FILE: assignSafeCall.kt } public final fun test_3(x: R|kotlin/Any?|): R|kotlin/Unit| { - lval a: R|B| = when (lval : R|B?| = (R|/x| as? R|B|)) { - ==($subj$, Null(null)) -> { - ^test_3 Unit - } - else -> { - R|/| - } - } - + lval a: R|B| = (R|/x| as? R|B|) ?: ^test_3 Unit R|/a|.R|/B.foo|() R|/x|.R|/B.foo|() } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.kt new file mode 100644 index 00000000000..3a145269754 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.kt @@ -0,0 +1,18 @@ +// ISSUE: KT-39074 + +interface A +interface B : A { + fun bar() +} + +fun materialize(): K? = null!! + +fun foo(b: B, cond: Boolean) { + val x = // inferred as A + if (cond) + b + else + materialize() ?: return + + x.bar() +} diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.txt index 3923ddcd917..6f331f220ed 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.txt @@ -6,25 +6,17 @@ FILE: ifElvisReturn.kt } public final fun materialize(): R|K?| { - ^materialize R|kotlin/TODO|() + ^materialize Null(null)!! } - public final fun foo(b: R|B|): R|kotlin/Unit| { - lval x: R|A| = when () { - CMP(>, R|/b|.R|kotlin/Any.hashCode|().R|kotlin/Int.compareTo|(Int(0))) -> { + public final fun foo(b: R|B|, cond: R|kotlin/Boolean|): R|kotlin/Unit| { + lval x: R|B| = when () { + R|/cond| -> { R|/b| } else -> { - when (lval : R|A?| = R|/materialize|()) { - ==($subj$, Null(null)) -> { - ^foo Unit - } - else -> { - R|/| - } - } - + R|/materialize|() ?: ^foo Unit } } - R|/x|.#() + R|/x|.R|/B.bar|() } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MapCompute.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MapCompute.txt index 7599eea8c38..c72dbf9a3f5 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MapCompute.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/MapCompute.txt @@ -1,15 +1,7 @@ FILE: MapCompute.kt public final fun R|kotlin/collections/MutableMap>|.initAndAdd(key: R|kotlin/String|, value: R|D|): R|kotlin/Unit| { this@R|/initAndAdd|.R|FakeOverride?|>|(R|/key|, = compute@fun (_: R|ft!|, maybeValues: R|ft, kotlin/collections/MutableSet?>!|): R|ft, kotlin/collections/MutableSet?>!| { - lval setOfValues: R|kotlin/collections/MutableSet| = when (lval : R|ft, kotlin/collections/MutableSet?>!| = R|/maybeValues|) { - ==($subj$, Null(null)) -> { - R|kotlin/collections/mutableSetOf|() - } - else -> { - R|/| - } - } - + lval setOfValues: R|kotlin/collections/MutableSet| = R|/maybeValues| ?: R|kotlin/collections/mutableSetOf|() R|/setOfValues|.R|FakeOverride|(R|/value|) ^ R|/setOfValues| } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 63af1a4a7a7..1ef7ea8023a 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -1484,6 +1484,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); } + @TestMetadata("lambdaInElvis.kt") + public void testLambdaInElvis() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt"); + } + @TestMetadata("nestedExtensionFunctionType.kt") public void testNestedExtensionFunctionType() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 3faaf559f10..670d34c5a50 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -1484,6 +1484,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); } + @TestMetadata("lambdaInElvis.kt") + public void testLambdaInElvis() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt"); + } + @TestMetadata("nestedExtensionFunctionType.kt") public void testNestedExtensionFunctionType() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 4d8c06e939d..a75f8b23420 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -711,6 +711,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic public void testFlexibleTypeInSystem() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/flexibleTypeInSystem.kt"); } + + @TestMetadata("ifElvisReturn.kt") + public void testIfElvisReturn() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/ifElvisReturn.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k") diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt index b455f2e083e..db4c31afc0f 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/SyntheticCallableId.kt @@ -9,20 +9,28 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name object SyntheticCallableId { + private val syntheticPackageName: FqName = FqName("_synthetic") + val WHEN = CallableId( - FqName("_synthetic"), + syntheticPackageName, Name.identifier("WHEN_CALL") ) val TRY = CallableId( - FqName("_synthetic"), + syntheticPackageName, Name.identifier("TRY_CALL") ) val CHECK_NOT_NULL = CallableId( - FqName("_synthetic"), + syntheticPackageName, Name.identifier("CHECK_NOT_NULL_CALL") ) + + val ELVIS_NOT_NULL = CallableId( + syntheticPackageName, + Name.identifier("ELVIS_CALL") + ) + val ID = CallableId( - FqName("_synthetic"), + syntheticPackageName, Name.identifier("ID_CALL") ) } diff --git a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt index 2cd4fbbfcb5..619db970250 100644 --- a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt +++ b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt @@ -1359,6 +1359,12 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver +"!!" } + private fun FlowContent.generate(elvisCall: FirElvisCall) { + generate(elvisCall.lhs) + +" ?: " + generate(elvisCall.rhs) + } + @Suppress("UNUSED_PARAMETER") private fun FlowContent.generate(elseIfTrueCondition: FirElseIfTrueCondition) { keyword("else") @@ -1563,6 +1569,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver is FirOperatorCall -> generate(expression) is FirBinaryLogicExpression -> generate(expression) is FirCheckNotNullCall -> generate(expression) + is FirElvisCall -> generate(expression) is FirVarargArgumentsExpression -> generate(expression) is FirResolvedReifiedParameterReference -> generate(expression) is FirComparisonExpression -> generate(expression) diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 64664e8248c..17d466584b0 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -141,45 +141,12 @@ fun IElementType.toFirOperation(): FirOperation = } fun FirExpression.generateNotNullOrOther( - session: FirSession, other: FirExpression, caseId: String, baseSource: FirSourceElement?, -): FirWhenExpression { - val subjectName = Name.special("<$caseId>") - val subjectSource = baseSource?.withKind(FirFakeSourceElementKind.WhenGeneratedSubject) - val subjectVariable = generateTemporaryVariable(session, subjectSource, subjectName, this) - - @OptIn(FirContractViolation::class) - val ref = FirExpressionRef() - val subjectExpression = buildWhenSubjectExpression { - source = subjectSource - whenRef = ref - } - - return buildWhenExpression { + other: FirExpression, baseSource: FirSourceElement?, +): FirElvisCall { + return buildElvisCall { source = baseSource - this.subject = this@generateNotNullOrOther - this.subjectVariable = subjectVariable - branches += buildWhenBranch { - val branchSource = baseSource?.withKind(FirFakeSourceElementKind.WhenCondition) - source = branchSource - condition = buildOperatorCall { - source = branchSource - operation = FirOperation.EQ - argumentList = buildBinaryArgumentList( - subjectExpression, buildConstExpression(branchSource, FirConstKind.Null, null) - ) - } - result = buildSingleExpressionBlock(other) - } - branches += buildWhenBranch { - val otherSource = other.source?.withKind(FirFakeSourceElementKind.WhenCondition) - source = otherSource - condition = buildElseIfTrueCondition { - source = otherSource - } - result = buildSingleExpressionBlock(generateResolvedAccessExpression(otherSource, subjectVariable)) - } - }.also { - ref.bind(it) + lhs = this@generateNotNullOrOther + rhs = other } } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 32006123929..f96791c4521 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -246,7 +246,7 @@ class ExpressionsConverter( when (operationToken) { ELVIS -> - return leftArgAsFir.generateNotNullOrOther(baseSession, rightArgAsFir, "elvis", baseSource) + return leftArgAsFir.generateNotNullOrOther(rightArgAsFir, baseSource) ANDAND, OROR -> return leftArgAsFir.generateLazyLogicalOperation(rightArgAsFir, operationToken == ANDAND, baseSource) in OperatorConventions.IN_OPERATIONS -> 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 21acc3a9eca..cccc6ef9856 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 @@ -1554,7 +1554,7 @@ class RawFirBuilder( when (operationToken) { ELVIS -> - return leftArgument.generateNotNullOrOther(baseSession, rightArgument, "elvis", source) + return leftArgument.generateNotNullOrOther(rightArgument, source) ANDAND, OROR -> return leftArgument.generateLazyLogicalOperation(rightArgument, operationToken == ANDAND, source) in OperatorConventions.IN_OPERATIONS -> diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/nullability.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/nullability.txt index 1221c05701c..d921ab37275 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/nullability.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/nullability.txt @@ -1,14 +1,6 @@ FILE: nullability.kt public? final? fun orFourtyTwo(arg: Int?): { - ^orFourtyTwo when (lval : = arg#) { - ==($subj$, Null(null)) -> { - IntegerLiteral(42) - } - else -> { - R|/| - } - } - + ^orFourtyTwo arg# ?: IntegerLiteral(42) } public? final? fun bang(arg: Int?): { ^bang arg#!! diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index c3e6ac33038..c42e0c2fd59 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -42,7 +42,7 @@ fun Candidate.resolveArgumentExpression( isDispatch: Boolean ) { when (argument) { - is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall -> resolveSubCallArgument( + is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall, is FirElvisCall -> resolveSubCallArgument( csBuilder, argument as FirResolvable, expectedType, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt index a27f2b2a361..a0606da2c5e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt @@ -116,7 +116,8 @@ fun PostponedArgumentsAnalyzer.Context.addSubsystemFromExpression(statement: Fir is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall, - is FirCallableReferenceAccess + is FirCallableReferenceAccess, + is FirElvisCall -> (statement as FirResolvable).candidate()?.let { addOtherSystem(it.system.asReadOnlyStorage()) } is FirSafeCallExpression -> addSubsystemFromExpression(statement.regularQualifiedAccess) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 8637800628e..a7b4731e70f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -1015,6 +1015,37 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitContractDescription() } + // ----------------------------------- Elvis ----------------------------------- + + fun exitElvisLhs(elvisCall: FirElvisCall) { + val (lhsExitNode, lhsIsNotNullNode, rhsEnterNode) = graphBuilder.exitElvisLhs(elvisCall) + lhsExitNode.mergeIncomingFlow() + val flow = lhsExitNode.flow + val lhsVariable = variableStorage.getOrCreateVariable(flow, elvisCall.lhs) + rhsEnterNode.flow = logicSystem.approveStatementsInsideFlow( + flow, + lhsVariable eq null, + shouldForkFlow = true, + shouldRemoveSynthetics = false + ) + lhsIsNotNullNode.flow = logicSystem.approveStatementsInsideFlow( + flow, + lhsVariable notEq null, + shouldForkFlow = true, + shouldRemoveSynthetics = false + ).also { + if (lhsVariable.isReal()) { + it.addTypeStatement(lhsVariable typeEq any) + } + } + } + + fun exitElvis(callCompleted: Boolean) { + val (elvisExitNode, unionNode) = graphBuilder.exitElvis(callCompleted) + elvisExitNode.mergeIncomingFlow() + unionNode?.let { unionFlowFromArguments(it) } + } + // ------------------------------------------------------ Utils ------------------------------------------------------ private var CFGNode<*>.flow: FLOW diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt index dd1481b560f..aaa2d7aaf34 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt @@ -601,6 +601,32 @@ class ExitSafeCallNode(owner: ControlFlowGraph, override val fir: FirSafeCallExp } } +// ----------------------------------- Elvis ----------------------------------- + +class ElvisLhsExitNode(owner: ControlFlowGraph, override val fir: FirElvisCall, level: Int, id: Int) : CFGNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitElvisLhsExitNode(this, data) + } +} + +class ElvisLhsIsNotNullNode(owner: ControlFlowGraph, override val fir: FirElvisCall, level: Int, id: Int) : CFGNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitElvisLhsIsNotNullNode(this, data) + } +} + +class ElvisRhsEnterNode(owner: ControlFlowGraph, override val fir: FirElvisCall, level: Int, id: Int) : CFGNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitElvisRhsEnterNode(this, data) + } +} + +class ElvisExitNode(owner: ControlFlowGraph, override val fir: FirElvisCall, level: Int, id: Int) : AbstractBinaryExitNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitElvisExitNode(this, data) + } +} + // ----------------------------------- Other ----------------------------------- class AnnotationEnterNode(owner: ControlFlowGraph, override val fir: FirAnnotationCall, level: Int, id: Int) : CFGNode(owner, level, id), EnterNodeMarker { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt index 37d0a367c1a..2ad5c533238 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt @@ -106,10 +106,15 @@ fun CFGNode<*>.render(): String = is ContractDescriptionEnterNode -> "Enter contract description" - is AbstractBinaryExitNode -> throw IllegalStateException() - is EnterDefaultArgumentsNode -> "Enter default value of ${fir.name}" is ExitDefaultArgumentsNode -> "Exit default value of ${fir.name}" + + is ElvisLhsExitNode -> "Exit lhs of ?:" + is ElvisLhsIsNotNullNode -> "Lhs of ?: is not null" + is ElvisRhsEnterNode -> "Enter rhs of ?:" + is ElvisExitNode -> "Exit ?:" + + is AbstractBinaryExitNode -> throw IllegalStateException() }, ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 96437065915..65feab47dc8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -91,6 +91,7 @@ class ControlFlowGraphBuilder { private val initBlockExitNodes: Stack = stackOf() private val exitSafeCallNodes: Stack = stackOf() + private val exitElvisCallNodes: Stack = stackOf() // ----------------------------------- API for node builders ----------------------------------- @@ -986,6 +987,37 @@ class ControlFlowGraphBuilder { } } + // ----------------------------------- Elvis ----------------------------------- + + fun exitElvisLhs(elvisCall: FirElvisCall): Triple { + val exitNode = createElvisExitNode(elvisCall).also { + exitElvisCallNodes.push(it) + } + + val lhsExitNode = createElvisLhsExitNode(elvisCall).also { + popAndAddEdge(it) + } + + val lhsIsNotNullNode = createElvisLhsIsNotNullNode(elvisCall).also { + addEdge(lhsExitNode, it) + addEdge(it, exitNode) + } + + val rhsEnterNode = createElvisRhsEnterNode(elvisCall).also { + addEdge(lhsExitNode, it) + } + lastNodes.push(rhsEnterNode) + return Triple(lhsExitNode, lhsIsNotNullNode, rhsEnterNode) + } + + fun exitElvis(callCompleted: Boolean): Pair { + val exitNode = exitElvisCallNodes.pop() + addNewSimpleNode(exitNode) + exitNode.updateDeadStatus() + val (_, unionNode) = processUnionOfArguments(exitNode, callCompleted) + return exitNode to unionNode + } + // ----------------------------------- Contract description ----------------------------------- fun enterContractDescription(): CFGNode<*> { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt index e49b9f0b579..36355fea5bc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt @@ -125,6 +125,18 @@ fun ControlFlowGraphBuilder.createAnnotationExitNode(fir: FirAnnotationCall): An fun ControlFlowGraphBuilder.createAnnotationEnterNode(fir: FirAnnotationCall): AnnotationEnterNode = AnnotationEnterNode(currentGraph, fir, levelCounter, createId()) +fun ControlFlowGraphBuilder.createElvisLhsIsNotNullNode(fir: FirElvisCall): ElvisLhsIsNotNullNode = + ElvisLhsIsNotNullNode(currentGraph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createElvisRhsEnterNode(fir: FirElvisCall): ElvisRhsEnterNode = + ElvisRhsEnterNode(currentGraph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createElvisLhsExitNode(fir: FirElvisCall): ElvisLhsExitNode = + ElvisLhsExitNode(currentGraph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createElvisExitNode(fir: FirElvisCall): ElvisExitNode = + ElvisExitNode(currentGraph, fir, levelCounter, createId()) + fun ControlFlowGraphBuilder.createVariableDeclarationNode(fir: FirProperty): VariableDeclarationNode = VariableDeclarationNode(currentGraph, fir, levelCounter, createId()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt index 5053141bfa3..c0fe5172480 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt @@ -307,6 +307,24 @@ abstract class ControlFlowGraphVisitor { return visitNode(node, data) } + // ----------------------------------- Elvis ----------------------------------- + + open fun visitElvisLhsExitNode(node: ElvisLhsExitNode, data: D): R { + return visitNode(node, data) + } + + open fun visitElvisLhsIsNotNullNode(node: ElvisLhsIsNotNullNode, data: D): R { + return visitNode(node, data) + } + + open fun visitElvisRhsEnterNode(node: ElvisRhsEnterNode, data: D): R { + return visitNode(node, data) + } + + open fun visitElvisExitNode(node: ElvisExitNode, data: D): R { + return visitNode(node, data) + } + // ----------------------------------- Other ----------------------------------- open fun visitAnnotationEnterNode(node: AnnotationEnterNode, data: D): R { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt index 8b68d845247..06d32466ee2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt @@ -292,6 +292,12 @@ fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, proc processCandidateIfApplicable(processor, processBlocks) this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) } } + + is FirElvisCall -> { + processCandidateIfApplicable(processor, processBlocks) + lhs.processAllContainingCallCandidates(processBlocks, processor) + rhs.processAllContainingCallCandidates(processBlocks, processor) + } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index c0c75decac6..b261421cbc4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -423,14 +423,21 @@ class FirCallCompletionResultsWriterTransformer( // Transformations for synthetic calls generated by FirSyntheticCallGenerator - override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ExpectedArgumentType?) = - transformSyntheticCall(whenExpression, data) + override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ExpectedArgumentType?): CompositeTransformResult { + return transformSyntheticCall(whenExpression, data) + } - override fun transformTryExpression(tryExpression: FirTryExpression, data: ExpectedArgumentType?) = - transformSyntheticCall(tryExpression, data) + override fun transformTryExpression(tryExpression: FirTryExpression, data: ExpectedArgumentType?): CompositeTransformResult { + return transformSyntheticCall(tryExpression, data) + } - override fun transformCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: ExpectedArgumentType?) = - transformSyntheticCall(checkNotNullCall, data) + override fun transformCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: ExpectedArgumentType?): CompositeTransformResult { + return transformSyntheticCall(checkNotNullCall, data) + } + + override fun transformElvisCall(elvisCall: FirElvisCall, data: ExpectedArgumentType?): CompositeTransformResult { + return transformSyntheticCall(elvisCall, data) + } private inline fun transformSyntheticCall( syntheticCall: D, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index bc706467952..a83f8ded27f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.SyntheticCallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -47,6 +48,7 @@ class FirSyntheticCallGenerator( private val trySelectFunction: FirSimpleFunction = generateSyntheticSelectFunction(SyntheticCallableId.TRY) private val idFunction: FirSimpleFunction = generateSyntheticSelectFunction(SyntheticCallableId.ID) private val checkNotNullFunction: FirSimpleFunction = generateSyntheticCheckNotNullFunction() + private val elvisFunction: FirSimpleFunction = generateSyntheticElvisFunction() fun generateCalleeForWhenExpression(whenExpression: FirWhenExpression): FirWhenExpression? { val stubReference = whenExpression.calleeReference @@ -101,6 +103,22 @@ class FirSyntheticCallGenerator( return checkNotNullCall.transformCalleeReference(UpdateReference, reference) } + fun generateCalleeForElvisCall(elvisCall: FirElvisCall): FirElvisCall? { + if (elvisCall.calleeReference !is FirStubReference) return null + + val argumentList = buildArgumentList { + arguments += elvisCall.lhs + arguments += elvisCall.rhs + } + val reference = generateCalleeReferenceWithCandidate( + elvisFunction, + argumentList, + SyntheticCallableId.ELVIS_NOT_NULL.callableName + ) ?: return null + + return elvisCall.transformCalleeReference(UpdateReference, reference) + } + fun resolveCallableReferenceWithSyntheticOuterCall( callableReferenceAccess: FirCallableReferenceAccess, expectedTypeRef: FirTypeRef? @@ -225,6 +243,42 @@ class FirSyntheticCallGenerator( }.build() } + private fun generateSyntheticElvisFunction(): FirSimpleFunction { + // Synthetic function signature: + // fun checkNotNull(x: K?, y: K): @Exact K + // + // Note: The upper bound of `K` cannot be `Any` because of the following case: + // fun test(a: X, b: X) = a ?: b + // `X` is not a subtype of `Any` and hence cannot satisfy `K` if it had an upper bound of `Any`. + val functionSymbol = FirSyntheticFunctionSymbol(SyntheticCallableId.ELVIS_NOT_NULL) + val (typeParameter, rightArgumentType) = generateSyntheticSelectTypeParameter() + + val leftArgumentType = buildResolvedTypeRef { + type = rightArgumentType.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE, session.typeContext) + } + + val returnType = rightArgumentType.resolvedTypeFromPrototype( + rightArgumentType.type.withAttributes( + ConeAttributes.create(listOf(CompilerConeAttributes.Exact)) + ) + ) + + val typeArgument = buildTypeProjectionWithVariance { + typeRef = returnType + variance = Variance.INVARIANT + } + + return generateMemberFunction( + functionSymbol, + SyntheticCallableId.ELVIS_NOT_NULL.callableName, + typeArgument.typeRef + ).apply { + typeParameters += typeParameter + valueParameters += leftArgumentType.toValueParameter("x") + valueParameters += rightArgumentType.toValueParameter("y") + }.build() + } + private fun generateMemberFunction( symbol: FirNamedFunctionSymbol, name: Name, returnType: FirTypeRef ): FirSimpleFunctionBuilder { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index d9824f02c7a..ee4b32c91c5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -304,6 +304,10 @@ open class FirBodyResolveTransformer( return controlFlowStatementsTransformer.transformThrowExpression(throwExpression, data) } + override fun transformElvisCall(elvisCall: FirElvisCall, data: ResolutionMode): CompositeTransformResult { + return controlFlowStatementsTransformer.transformElvisCall(elvisCall, data) + } + // -------------------------------------------------------------------------- fun FirElement.visitNoTransform(transformer: FirTransformer, data: D) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 4bee7cedb47..69f2b950d22 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -208,4 +208,31 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran dataFlowAnalyzer.exitThrowExceptionNode(it.single as FirThrowExpression) } } + + // ------------------------------- Elvis ------------------------------- + + override fun transformElvisCall(elvisCall: FirElvisCall, data: ResolutionMode): CompositeTransformResult { + if (elvisCall.calleeReference is FirResolvedNamedReference) return elvisCall.compose() + elvisCall.transformAnnotations(transformer, data) + elvisCall.transformLhs(transformer, ResolutionMode.ContextDependent) + dataFlowAnalyzer.exitElvisLhs(elvisCall) + elvisCall.transformRhs(transformer, ResolutionMode.ContextDependent) + + var callCompleted = false + val result = syntheticCallGenerator.generateCalleeForElvisCall(elvisCall)?.let { + val completionResult = callCompleter.completeCall(elvisCall, data.expectedType) + callCompleted = completionResult.callCompleted + completionResult.result + } ?: run { + elvisCall.resultType = buildErrorTypeRef { + diagnostic = ConeSimpleDiagnostic("Can't resolve ?: operator call", DiagnosticKind.InferenceError) + } + callCompleted = true + elvisCall + } + + dataFlowAnalyzer.exitElvis(callCompleted) + + return result.compose() + } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 84912827745..7f037c424b3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -6,14 +6,12 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl -import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.name.ClassId @@ -22,7 +20,6 @@ import org.jetbrains.kotlin.types.AbstractNullabilityChecker import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.utils.addToStdlib.safeAs object ConeNullabilityChecker { fun isSubtypeOfAny(context: ConeTypeContext, type: ConeKotlinType): Boolean { @@ -106,6 +103,21 @@ fun T.withArguments(arguments: Array T.withAttributes(attributes: ConeAttributes): T { + if (this.attributes == attributes) { + return this + } + + @Suppress("UNCHECKED_CAST") + return when (this) { + is ConeClassErrorType -> this + is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable, attributes) + is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType.create(original.withAttributes(attributes))!! + is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes) + else -> error("Not supported: $this: ${this.render()}") + } as T +} + fun ConeTypeContext.hasNullableSuperType(type: ConeKotlinType): Boolean { if (type is ConeClassLikeType) return false diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index a2dcf372e09..97fd561cb11 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -1022,6 +1022,12 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM print("!!") } + override fun visitElvisCall(elvisCall: FirElvisCall) { + elvisCall.lhs.accept(this) + print(" ?: ") + elvisCall.rhs.accept(this) + } + override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) { callableReferenceAccess.annotations.renderAnnotations() callableReferenceAccess.explicitReceiver?.accept(this) diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.fir.kt index 80ba65790b1..7d4688e80cc 100644 --- a/compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.fir.kt @@ -15,5 +15,5 @@ fun test(s: String?, silent: Boolean) { throw Exception() } - s.length + s.length } diff --git a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.fir.kt b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.fir.kt index 6a169949d59..72e3bcca902 100644 --- a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.fir.kt +++ b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.fir.kt @@ -42,7 +42,7 @@ fun test() { inline fun reifiedNull(): T? = null fun testFrom13648() { - takeNotNull(reifiedNull() ?: "") + takeNotNull(reifiedNull() ?: "") } fun bar() = unresolved \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/inferenceForElvis.fir.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/inferenceForElvis.fir.kt index acf00f5938c..06ba1f69025 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/inferenceForElvis.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/inferenceForElvis.fir.kt @@ -3,6 +3,6 @@ fun foo(f: (T) -> Unit): T? = null // T is used only as return type fun test() { - val x = foo { it checkType { _() }} ?: "" // foo() is inferred as foo, which isn't very good - val y: Any = foo { it checkType { _() } } ?: "" // but for now it's fixed by specifying expected type + val x = foo { it checkType { _() }} ?: "" // foo() is inferred as foo, which isn't very good + val y: Any = foo { it checkType { _() } } ?: "" // but for now it's fixed by specifying expected type } \ No newline at end of file diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/32.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/32.fir.kt index e722dae978a..d92d04b74a1 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/32.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/32.fir.kt @@ -6,7 +6,7 @@ fun case_1(x: T?, y: K?) { x as T y as K - val z = x ?: y + val z = x ?: y x.equals(10) z