FIR CFG: add one more test case
This commit is contained in:
+110
@@ -339,4 +339,114 @@ digraph flowFromTwoInplaceLambdas_kt {
|
|||||||
120 -> {94} [color=red];
|
120 -> {94} [color=red];
|
||||||
120 -> {97} [color=green];
|
120 -> {97} [color=green];
|
||||||
|
|
||||||
|
subgraph cluster_25 {
|
||||||
|
color=red
|
||||||
|
121 [label="Enter class I1" style="filled" fillcolor=red];
|
||||||
|
122 [label="Exit class I1" style="filled" fillcolor=red];
|
||||||
|
}
|
||||||
|
121 -> {122} [color=green];
|
||||||
|
|
||||||
|
subgraph cluster_26 {
|
||||||
|
color=red
|
||||||
|
123 [label="Enter class I2" style="filled" fillcolor=red];
|
||||||
|
124 [label="Exit class I2" style="filled" fillcolor=red];
|
||||||
|
}
|
||||||
|
123 -> {124} [color=green];
|
||||||
|
|
||||||
|
subgraph cluster_27 {
|
||||||
|
color=red
|
||||||
|
125 [label="Enter function test4" style="filled" fillcolor=red];
|
||||||
|
subgraph cluster_28 {
|
||||||
|
color=blue
|
||||||
|
126 [label="Enter block"];
|
||||||
|
127 [label="Access variable R|<local>/x|"];
|
||||||
|
128 [label="Access variable <Unresolved name: x>#"];
|
||||||
|
129 [label="Access variable R|<local>/x|"];
|
||||||
|
130 [label="Access variable <Unresolved name: y>#"];
|
||||||
|
131 [label="Postponed enter to lambda"];
|
||||||
|
subgraph cluster_29 {
|
||||||
|
color=blue
|
||||||
|
143 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
|
||||||
|
subgraph cluster_30 {
|
||||||
|
color=blue
|
||||||
|
144 [label="Enter block"];
|
||||||
|
145 [label="Access variable R|<local>/x|"];
|
||||||
|
146 [label="Type operator: (R|<local>/x| as R|I1|)"];
|
||||||
|
147 [label="Access variable R|<local>/x|"];
|
||||||
|
148 [label="Access variable <Unresolved name: y>#"];
|
||||||
|
149 [label="Function call: R|/n|<R|kotlin/Int?|>()"];
|
||||||
|
150 [label="Exit block"];
|
||||||
|
}
|
||||||
|
151 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||||
|
}
|
||||||
|
133 [label="Postponed exit from lambda"];
|
||||||
|
134 [label="Postponed enter to lambda"];
|
||||||
|
subgraph cluster_31 {
|
||||||
|
color=blue
|
||||||
|
152 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
|
||||||
|
subgraph cluster_32 {
|
||||||
|
color=blue
|
||||||
|
153 [label="Enter block"];
|
||||||
|
154 [label="Access variable R|<local>/x|"];
|
||||||
|
155 [label="Type operator: (R|<local>/x| as R|I2|)"];
|
||||||
|
156 [label="Access variable R|<local>/x|"];
|
||||||
|
157 [label="Access variable <Unresolved name: x>#"];
|
||||||
|
158 [label="Const: Int(123)"];
|
||||||
|
159 [label="Exit block"];
|
||||||
|
}
|
||||||
|
160 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||||
|
}
|
||||||
|
132 [label="Call arguments union" style="filled" fillcolor=yellow];
|
||||||
|
135 [label="Postponed exit from lambda"];
|
||||||
|
136 [label="Function call: R|/run2|<R|kotlin/Int?|>(...)"];
|
||||||
|
137 [label="Access variable R|<local>/x|"];
|
||||||
|
138 [label="Access variable R|/I1.x|"];
|
||||||
|
139 [label="Access variable R|<local>/x|"];
|
||||||
|
140 [label="Access variable R|/I2.y|"];
|
||||||
|
141 [label="Exit block"];
|
||||||
|
}
|
||||||
|
142 [label="Exit function test4" style="filled" fillcolor=red];
|
||||||
|
}
|
||||||
|
125 -> {126};
|
||||||
|
126 -> {127};
|
||||||
|
127 -> {128};
|
||||||
|
128 -> {129};
|
||||||
|
129 -> {130};
|
||||||
|
130 -> {131};
|
||||||
|
131 -> {143};
|
||||||
|
131 -> {133} [color=red];
|
||||||
|
131 -> {143} [style=dashed];
|
||||||
|
132 -> {136} [color=red];
|
||||||
|
133 -> {134};
|
||||||
|
134 -> {152};
|
||||||
|
134 -> {135} [color=red];
|
||||||
|
134 -> {152} [style=dashed];
|
||||||
|
135 -> {136} [color=green];
|
||||||
|
136 -> {137};
|
||||||
|
137 -> {138};
|
||||||
|
138 -> {139};
|
||||||
|
139 -> {140};
|
||||||
|
140 -> {141};
|
||||||
|
141 -> {142};
|
||||||
|
143 -> {144};
|
||||||
|
144 -> {145};
|
||||||
|
145 -> {146};
|
||||||
|
146 -> {147};
|
||||||
|
147 -> {148};
|
||||||
|
148 -> {149};
|
||||||
|
149 -> {150};
|
||||||
|
150 -> {151};
|
||||||
|
151 -> {132} [color=red];
|
||||||
|
151 -> {133} [color=green];
|
||||||
|
152 -> {153};
|
||||||
|
153 -> {154};
|
||||||
|
154 -> {155};
|
||||||
|
155 -> {156};
|
||||||
|
156 -> {157};
|
||||||
|
157 -> {158};
|
||||||
|
158 -> {159};
|
||||||
|
159 -> {160};
|
||||||
|
160 -> {132} [color=red];
|
||||||
|
160 -> {135} [color=green];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -61,3 +61,30 @@ FILE: flowFromTwoInplaceLambdas.kt
|
|||||||
R|<local>/p|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
|
R|<local>/p|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
|
||||||
R|<local>/p|?.{ $subj$.R|kotlin/String.length| }
|
R|<local>/p|?.{ $subj$.R|kotlin/String.length| }
|
||||||
}
|
}
|
||||||
|
public abstract interface I1 : R|kotlin/Any| {
|
||||||
|
public abstract val x: R|kotlin/Int|
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface I2 : R|kotlin/Any| {
|
||||||
|
public abstract val y: R|kotlin/Int|
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun test4(x: R|kotlin/Any?|): R|kotlin/Unit| {
|
||||||
|
R|<local>/x|.<Unresolved name: x>#
|
||||||
|
R|<local>/x|.<Unresolved name: y>#
|
||||||
|
R|/run2|<R|kotlin/Int?|>(run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||||
|
(R|<local>/x| as R|I1|)
|
||||||
|
R|<local>/x|.<Unresolved name: y>#
|
||||||
|
^ R|/n|<R|kotlin/Int?|>()
|
||||||
|
}
|
||||||
|
, run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||||
|
(R|<local>/x| as R|I2|)
|
||||||
|
R|<local>/x|.<Unresolved name: x>#
|
||||||
|
^ Int(123)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/x|.R|/I1.x|
|
||||||
|
R|<local>/x|.R|/I2.y|
|
||||||
|
}
|
||||||
|
|||||||
+16
-2
@@ -28,7 +28,7 @@ fun test2(x: Any?) {
|
|||||||
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
||||||
run2({ p = null; n() }, { p as String; 123 })
|
run2({ p = null; n() }, { p as String; 123 })
|
||||||
p<!UNSAFE_CALL!>.<!>length // Bad: p can be null
|
p<!UNSAFE_CALL!>.<!>length // Bad: p can be null
|
||||||
p?.length // OK: p is either null or String
|
p?.length // OK: p is String | Nothing? = String?
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test3(x: Any?) {
|
fun test3(x: Any?) {
|
||||||
@@ -36,5 +36,19 @@ fun test3(x: Any?) {
|
|||||||
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
||||||
run2({ p = null; n() }, { p = ""; 123 })
|
run2({ p = null; n() }, { p = ""; 123 })
|
||||||
p<!UNSAFE_CALL!>.<!>length // Bad: p can be null
|
p<!UNSAFE_CALL!>.<!>length // Bad: p can be null
|
||||||
p?.length // OK: p is either null or String
|
p?.length // OK: p is String | Nothing? = String?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I1 { val x: Int }
|
||||||
|
interface I2 { val y: Int }
|
||||||
|
|
||||||
|
fun test4(x: Any?) {
|
||||||
|
x.<!UNRESOLVED_REFERENCE!>x<!> // Bad
|
||||||
|
x.<!UNRESOLVED_REFERENCE!>y<!> // Bad
|
||||||
|
run2(
|
||||||
|
{ x as I1; x.<!UNRESOLVED_REFERENCE!>y<!>; n() }, // Bad: may or may not be called first
|
||||||
|
{ x as I2; x.<!UNRESOLVED_REFERENCE!>x<!>; 123 } // Bad: may or may not be called first
|
||||||
|
)
|
||||||
|
x.x // OK: x is I1 & I2
|
||||||
|
x.y // OK: x is I1 & I2
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user