FIR DFA: take all statements from ?. if result is non-null.

I.e. a?.f(b as T) != null => b is T.

This also allows to remove the copyAllInformationFrom hack by moving the
edge directly in the control flow graph.
This commit is contained in:
pyos
2022-11-19 19:13:27 +01:00
committed by teamcity
parent 3392e066df
commit 16b8811697
14 changed files with 278 additions and 245 deletions
@@ -40,51 +40,116 @@ digraph safeCalls_kt {
10 [label="Access variable R|<local>/x|"];
11 [label="Enter safe call"];
12 [label="Function call: $subj$.R|/A.foo|()"];
13 [label="Exit safe call"];
14 [label="Enter safe call"];
15 [label="Function call: $subj$.R|/A.bar|()"];
13 [label="Enter safe call"];
14 [label="Const: String()"];
15 [label="Function call: $subj$.R|/A.bar|(...)"];
16 [label="Exit safe call"];
17 [label="Exit block"];
17 [label="Exit safe call"];
18 [label="Exit block"];
}
18 [label="Exit function test_1" style="filled" fillcolor=red];
19 [label="Exit function test_1" style="filled" fillcolor=red];
}
8 -> {9};
9 -> {10};
10 -> {11 13};
10 -> {11 16};
11 -> {12};
12 -> {13};
13 -> {14 16};
12 -> {16 13};
13 -> {14};
14 -> {15};
15 -> {16};
15 -> {17};
16 -> {17};
17 -> {18};
18 -> {19};
subgraph cluster_6 {
color=red
19 [label="Enter function test_2" style="filled" fillcolor=red];
20 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_7 {
color=blue
20 [label="Enter block"];
21 [label="Access variable R|<local>/x|"];
22 [label="Enter safe call"];
23 [label="Access variable R|/B.foo|"];
24 [label="Exit safe call"];
21 [label="Enter block"];
22 [label="Access variable R|<local>/x|"];
23 [label="Enter safe call"];
24 [label="Access variable R|/B.foo|"];
25 [label="Enter safe call"];
26 [label="Access variable R|/B.bar|"];
27 [label="Exit safe call"];
28 [label="Exit block"];
28 [label="Exit safe call"];
29 [label="Exit block"];
}
29 [label="Exit function test_2" style="filled" fillcolor=red];
30 [label="Exit function test_2" style="filled" fillcolor=red];
}
19 -> {20};
20 -> {21};
21 -> {22 24};
22 -> {23};
21 -> {22};
22 -> {23 27};
23 -> {24};
24 -> {25 27};
24 -> {27 25};
25 -> {26};
26 -> {27};
26 -> {28};
27 -> {28};
28 -> {29};
29 -> {30};
subgraph cluster_8 {
color=red
31 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_9 {
color=blue
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|<local>/x|"];
36 [label="Enter safe call"];
37 [label="Access variable R|<local>/y|"];
38 [label="Type operator: (R|<local>/y| as R|kotlin/String|)"];
39 [label="Function call: $subj$.R|/A.bar|(...)"];
40 [label="Exit safe call"];
41 [label="Const: Null(null)"];
42 [label="Equality operator !="];
43 [label="Exit when branch condition"];
}
44 [label="Synthetic else branch"];
45 [label="Enter when branch result"];
subgraph cluster_12 {
color=blue
46 [label="Enter block"];
47 [label="Access variable R|<local>/y|"];
48 [label="Smart cast: R|<local>/y|"];
49 [label="Access variable R|kotlin/String.length|"];
50 [label="Exit block"];
}
51 [label="Exit when branch result"];
52 [label="Exit when"];
}
53 [label="Exit block"];
}
54 [label="Exit function test_3" style="filled" fillcolor=red];
}
31 -> {32};
32 -> {33};
33 -> {34};
34 -> {35};
35 -> {36 40};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {42};
42 -> {43};
43 -> {45 44};
44 -> {52};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {54};
}
@@ -2,7 +2,7 @@ FILE: safeCalls.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|A|
public abstract fun bar(): R|A|
public abstract fun bar(x: R|kotlin/String|): R|A|
}
public abstract interface B : R|kotlin/Any| {
@@ -14,8 +14,16 @@ FILE: safeCalls.kt
}
public final fun test_1(x: R|A?|): R|kotlin/Unit| {
R|<local>/x|?.{ $subj$.R|/A.foo|() }?.{ $subj$.R|/A.bar|() }
R|<local>/x|?.{ $subj$.R|/A.foo|() }?.{ $subj$.R|/A.bar|(String()) }
}
public final fun test_2(x: R|B?|): R|kotlin/Unit| {
R|<local>/x|?.{ $subj$.R|/B.foo| }?.{ $subj$.R|/B.bar| }
}
public final fun test_3(x: R|A?|, y: R|kotlin/String?|): R|kotlin/Unit| {
when () {
!=(R|<local>/x|?.{ $subj$.R|/A.bar|((R|<local>/y| as R|kotlin/String|)) }, Null(null)) -> {
R|<local>/y|.R|kotlin/String.length|
}
}
}
@@ -1,7 +1,7 @@
// !DUMP_CFG
interface A {
fun foo(): A
fun bar(): A
fun bar(x: String): A
}
interface B {
@@ -10,9 +10,15 @@ interface B {
}
fun test_1(x: A?) {
x?.foo()?.bar()
x?.foo()?.bar("")
}
fun test_2(x: B?) {
x?.foo?.bar
}
fun test_3(x: A?, y: String?) {
if (x?.bar(y as String) != null) {
y.length
}
}
@@ -62,9 +62,7 @@ digraph elvis_kt {
5 -> {6};
6 -> {7};
7 -> {8};
8 -> {9};
8 -> {11} [color=red];
8 -> {13} [color=green];
8 -> {9 13};
9 -> {10};
10 -> {11};
11 -> {12};
@@ -490,9 +490,7 @@ digraph returns_kt {
161 -> {162};
162 -> {163};
163 -> {164};
164 -> {165};
164 -> {167} [color=red];
164 -> {169} [color=green];
164 -> {165 169};
165 -> {166};
166 -> {167};
167 -> {168};
@@ -484,12 +484,12 @@ digraph nullability_kt {
165 [label="Access variable R|<local>/q|"];
166 [label="Enter safe call"];
167 [label="Access variable R|/Q.data|"];
168 [label="Exit safe call"];
169 [label="Enter safe call"];
170 [label="Access variable R|/MyData.s|"];
171 [label="Exit safe call"];
172 [label="Enter safe call"];
173 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
168 [label="Enter safe call"];
169 [label="Access variable R|/MyData.s|"];
170 [label="Enter safe call"];
171 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
172 [label="Exit safe call"];
173 [label="Exit safe call"];
174 [label="Exit safe call"];
175 [label="Const: Null(null)"];
176 [label="Equality operator !="];
@@ -528,13 +528,13 @@ digraph nullability_kt {
162 -> {163};
163 -> {164};
164 -> {165};
165 -> {166 168};
165 -> {166 172};
166 -> {167};
167 -> {168};
168 -> {169 171};
169 -> {170};
167 -> {172 168};
168 -> {169};
169 -> {173 170};
170 -> {171};
171 -> {172 174};
171 -> {174};
172 -> {173};
173 -> {174};
174 -> {175};
@@ -573,18 +573,18 @@ digraph nullability_kt {
203 [label="Access variable R|<local>/q|"];
204 [label="Enter safe call"];
205 [label="Access variable R|/Q.data|"];
206 [label="Exit safe call"];
207 [label="Enter safe call"];
208 [label="Access variable R|/MyData.s|"];
209 [label="Exit safe call"];
210 [label="Enter safe call"];
211 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
212 [label="Exit safe call"];
213 [label="Exit lhs of ?:"];
214 [label="Enter rhs of ?:"];
215 [label="Jump: ^test_6 Unit"];
216 [label="Stub" style="filled" fillcolor=gray];
217 [label="Lhs of ?: is not null"];
206 [label="Enter safe call"];
207 [label="Access variable R|/MyData.s|"];
208 [label="Enter safe call"];
209 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
210 [label="Exit safe call"];
211 [label="Exit lhs of ?:"];
212 [label="Lhs of ?: is not null"];
213 [label="Exit safe call"];
214 [label="Exit safe call"];
215 [label="Enter rhs of ?:"];
216 [label="Jump: ^test_6 Unit"];
217 [label="Stub" style="filled" fillcolor=gray];
218 [label="Exit ?:"];
219 [label="Access variable R|<local>/q|"];
220 [label="Smart cast: R|<local>/q|"];
@@ -607,24 +607,22 @@ digraph nullability_kt {
}
201 -> {202};
202 -> {203};
203 -> {204 206};
203 -> {204 213};
204 -> {205};
205 -> {206};
206 -> {207 209};
207 -> {208};
205 -> {213 206};
206 -> {207};
207 -> {214 208};
208 -> {209};
209 -> {210};
209 -> {212} [color=red];
209 -> {214} [color=green];
210 -> {211};
211 -> {212};
212 -> {213};
213 -> {217 214};
211 -> {212 215};
212 -> {218};
213 -> {214};
214 -> {215};
215 -> {235};
215 -> {216} [style=dotted];
216 -> {218} [style=dotted];
217 -> {218};
215 -> {216};
216 -> {235};
216 -> {217} [style=dotted];
217 -> {218} [style=dotted];
218 -> {219};
219 -> {220};
220 -> {221};
@@ -658,12 +656,12 @@ digraph nullability_kt {
240 [label="Access variable R|<local>/q|"];
241 [label="Enter safe call"];
242 [label="Function call: $subj$.R|/Q.fdata|()"];
243 [label="Exit safe call"];
244 [label="Enter safe call"];
245 [label="Function call: $subj$.R|/MyData.fs|()"];
246 [label="Exit safe call"];
247 [label="Enter safe call"];
248 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
243 [label="Enter safe call"];
244 [label="Function call: $subj$.R|/MyData.fs|()"];
245 [label="Enter safe call"];
246 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
247 [label="Exit safe call"];
248 [label="Exit safe call"];
249 [label="Exit safe call"];
250 [label="Const: Null(null)"];
251 [label="Equality operator !="];
@@ -699,13 +697,13 @@ digraph nullability_kt {
237 -> {238};
238 -> {239};
239 -> {240};
240 -> {241 243};
240 -> {241 247};
241 -> {242};
242 -> {243};
243 -> {244 246};
244 -> {245};
242 -> {247 243};
243 -> {244};
244 -> {248 245};
245 -> {246};
246 -> {247 249};
246 -> {249};
247 -> {248};
248 -> {249};
249 -> {250};
@@ -1164,12 +1162,12 @@ digraph nullability_kt {
436 [label="Access variable R|<local>/q|"];
437 [label="Enter safe call"];
438 [label="Access variable R|/QImpl.data|"];
439 [label="Exit safe call"];
440 [label="Enter safe call"];
441 [label="Access variable R|/MyData.s|"];
442 [label="Exit safe call"];
443 [label="Enter safe call"];
444 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
439 [label="Enter safe call"];
440 [label="Access variable R|/MyData.s|"];
441 [label="Enter safe call"];
442 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
443 [label="Exit safe call"];
444 [label="Exit safe call"];
445 [label="Exit safe call"];
446 [label="Const: Null(null)"];
447 [label="Equality operator !="];
@@ -1248,13 +1246,13 @@ digraph nullability_kt {
433 -> {434};
434 -> {435};
435 -> {436};
436 -> {437 439};
436 -> {437 443};
437 -> {438};
438 -> {439};
439 -> {440 442};
440 -> {441};
438 -> {443 439};
439 -> {440};
440 -> {444 441};
441 -> {442};
442 -> {443 445};
442 -> {445};
443 -> {444};
444 -> {445};
445 -> {446};
@@ -1330,12 +1328,12 @@ digraph nullability_kt {
507 [label="Access variable R|<local>/q|"];
508 [label="Enter safe call"];
509 [label="Access variable R|/QImplWithCustomGetter.data|"];
510 [label="Exit safe call"];
511 [label="Enter safe call"];
512 [label="Access variable R|/MyData.s|"];
513 [label="Exit safe call"];
514 [label="Enter safe call"];
515 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
510 [label="Enter safe call"];
511 [label="Access variable R|/MyData.s|"];
512 [label="Enter safe call"];
513 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
514 [label="Exit safe call"];
515 [label="Exit safe call"];
516 [label="Exit safe call"];
517 [label="Const: Null(null)"];
518 [label="Equality operator !="];
@@ -1374,13 +1372,13 @@ digraph nullability_kt {
504 -> {505};
505 -> {506};
506 -> {507};
507 -> {508 510};
507 -> {508 514};
508 -> {509};
509 -> {510};
510 -> {511 513};
511 -> {512};
509 -> {514 510};
510 -> {511};
511 -> {515 512};
512 -> {513};
513 -> {514 516};
513 -> {516};
514 -> {515};
515 -> {516};
516 -> {517};
@@ -1425,12 +1423,12 @@ digraph nullability_kt {
547 [label="Access variable R|<local>/q|"];
548 [label="Enter safe call"];
549 [label="Access variable R|/QImplMutable.data|"];
550 [label="Exit safe call"];
551 [label="Enter safe call"];
552 [label="Access variable R|/MyData.s|"];
553 [label="Exit safe call"];
554 [label="Enter safe call"];
555 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
550 [label="Enter safe call"];
551 [label="Access variable R|/MyData.s|"];
552 [label="Enter safe call"];
553 [label="Function call: $subj$.R|kotlin/Int.inc|()"];
554 [label="Exit safe call"];
555 [label="Exit safe call"];
556 [label="Exit safe call"];
557 [label="Const: Null(null)"];
558 [label="Equality operator !="];
@@ -1469,13 +1467,13 @@ digraph nullability_kt {
544 -> {545};
545 -> {546};
546 -> {547};
547 -> {548 550};
547 -> {548 554};
548 -> {549};
549 -> {550};
550 -> {551 553};
551 -> {552};
549 -> {554 550};
550 -> {551};
551 -> {555 552};
552 -> {553};
553 -> {554 556};
553 -> {556};
554 -> {555};
555 -> {556};
556 -> {557};
@@ -142,15 +142,13 @@ digraph safeCalls_kt {
50 [label="Access variable R|<local>/x|"];
51 [label="Smart cast: R|<local>/x|"];
52 [label="Function call: $subj$.R|/A.bar|(...)"];
53 [label="Exit safe call"];
54 [label="Enter safe call"];
55 [label="Access variable R|<local>/x|"];
56 [label="Smart cast: R|<local>/x|"];
57 [label="Function call: R|<local>/x|.R|/A.bool|()"];
58 [label="Function call: $subj$.R|/foo|(...)"];
59 [label="Exit safe call"];
60 [label="Enter safe call"];
61 [label="Postponed enter to lambda"];
53 [label="Enter safe call"];
54 [label="Access variable R|<local>/x|"];
55 [label="Smart cast: R|<local>/x|"];
56 [label="Function call: R|<local>/x|.R|/A.bool|()"];
57 [label="Function call: $subj$.R|/foo|(...)"];
58 [label="Enter safe call"];
59 [label="Postponed enter to lambda"];
subgraph cluster_14 {
color=blue
69 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
@@ -164,8 +162,10 @@ digraph safeCalls_kt {
}
75 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
62 [label="Postponed exit from lambda"];
63 [label="Function call: $subj$.R|/let|(...)"];
60 [label="Postponed exit from lambda"];
61 [label="Function call: $subj$.R|/let|(...)"];
62 [label="Exit safe call"];
63 [label="Exit safe call"];
64 [label="Exit safe call"];
65 [label="Access variable R|<local>/x|"];
66 [label="Function call: R|<local>/x|.<Unresolved name: bool>#()"];
@@ -176,21 +176,21 @@ digraph safeCalls_kt {
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49 53};
48 -> {49 62};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {54 59};
52 -> {62 53};
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {57};
57 -> {58};
57 -> {63 58};
58 -> {59};
59 -> {60 64};
59 -> {60 69};
59 -> {69} [style=dashed];
60 -> {61};
61 -> {62 69};
61 -> {69} [style=dashed];
61 -> {64};
62 -> {63};
63 -> {64};
64 -> {65};
@@ -213,9 +213,9 @@ digraph safeCalls_kt {
78 [label="Access variable R|<local>/x|"];
79 [label="Enter safe call"];
80 [label="Function call: $subj$.R|/A.id|()"];
81 [label="Exit safe call"];
82 [label="Enter safe call"];
83 [label="Function call: $subj$.R|/A.bool|()"];
81 [label="Enter safe call"];
82 [label="Function call: $subj$.R|/A.bool|()"];
83 [label="Exit safe call"];
84 [label="Exit safe call"];
85 [label="Access variable R|<local>/x|"];
86 [label="Function call: R|<local>/x|.<Inapplicable(UNSAFE_CALL): /A.id>#()"];
@@ -225,11 +225,11 @@ digraph safeCalls_kt {
}
76 -> {77};
77 -> {78};
78 -> {79 81};
78 -> {79 83};
79 -> {80};
80 -> {81};
81 -> {82 84};
82 -> {83};
80 -> {83 81};
81 -> {82};
82 -> {84};
83 -> {84};
84 -> {85};
85 -> {86};
@@ -275,12 +275,12 @@ digraph safeCalls_kt {
99 [label="Postponed exit from lambda" style="filled" fillcolor=gray];
100 [label="Function call: $subj$.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(...)" style="filled" fillcolor=gray];
101 [label="Stub" style="filled" fillcolor=gray];
102 [label="Exit safe call"];
103 [label="Enter safe call"];
104 [label="Access variable R|<local>/x|"];
105 [label="Smart cast: R|<local>/x|"];
106 [label="Function call: R|<local>/x|.R|/A.bool|()"];
107 [label="Function call: $subj$.R|/boo|(...)"];
102 [label="Enter safe call" style="filled" fillcolor=gray];
103 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
104 [label="Smart cast: R|<local>/x|" style="filled" fillcolor=gray];
105 [label="Function call: R|<local>/x|.R|/A.bool|()" style="filled" fillcolor=gray];
106 [label="Function call: $subj$.R|/boo|(...)" style="filled" fillcolor=gray];
107 [label="Exit safe call"];
108 [label="Exit safe call"];
109 [label="Access variable R|<local>/x|"];
110 [label="Function call: R|<local>/x|.<Inapplicable(UNSAFE_CALL): /A.id>#()"];
@@ -290,7 +290,7 @@ digraph safeCalls_kt {
}
93 -> {94};
94 -> {95};
95 -> {96 102};
95 -> {96 107};
96 -> {97};
97 -> {113};
97 -> {99} [color=red];
@@ -299,12 +299,12 @@ digraph safeCalls_kt {
99 -> {100} [style=dotted];
100 -> {101} [style=dotted];
100 -> {112} [style=dotted] [label=onUncaughtException];
101 -> {102} [style=dotted];
102 -> {103 108};
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {107};
101 -> {107 102} [style=dotted];
102 -> {103} [style=dotted];
103 -> {104} [style=dotted];
104 -> {105} [style=dotted];
105 -> {106} [style=dotted];
106 -> {108} [style=dotted];
107 -> {108};
108 -> {109};
109 -> {110};
@@ -139,9 +139,7 @@ digraph smartcastInByClause_kt {
}
24 -> {25};
25 -> {26};
26 -> {27};
26 -> {29} [color=red];
26 -> {31} [color=green];
26 -> {27 31};
27 -> {28};
28 -> {29};
29 -> {30};