FIR CFG: when unifying flows, group statements by assignment
Consider a function `run2` that has 2 lambda arguments called in place.
We don't know the order in which they're called, so here:
var x: Any? = something
run2(
{ x = null },
{ x as String },
)
// <--
it's not correct to simply `&&` the statements together, as that would
produce `x is Nothing? && x is String && x is Any?`. Instead, statements
should be grouped by assignment first, and different groups are `||`-ed.
This means in the above example we now get `x is Nothing? || (x is Any?
&& x is String)` == `x is String?`.
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
FILE: flowFromTwoInplaceLambdas.kt
|
||||
public final fun <T> n(): R|T?| {
|
||||
^n Null(null)
|
||||
}
|
||||
public final fun <T> run2(x: R|() -> T|, y: R|() -> T|): R|kotlin/Unit|
|
||||
[R|Contract description]
|
||||
<
|
||||
CallsInPlace(x, EXACTLY_ONCE)
|
||||
CallsInPlace(y, EXACTLY_ONCE)
|
||||
>
|
||||
{
|
||||
[StubStatement]
|
||||
R|<local>/x|.R|SubstitutionOverride<kotlin/Function0.invoke: R|T|>|()
|
||||
R|<local>/y|.R|SubstitutionOverride<kotlin/Function0.invoke: R|T|>|()
|
||||
}
|
||||
public final fun test1(x: R|kotlin/String?|): R|kotlin/Unit| {
|
||||
lvar p: R|kotlin/String?| = R|<local>/x|
|
||||
when () {
|
||||
!=(R|<local>/p|, Null(null)) -> {
|
||||
R|/run2|<R|kotlin/Int?|>(run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
R|<local>/p| = Null(null)
|
||||
^ R|/n|<R|kotlin/Int?|>()
|
||||
}
|
||||
, run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
R|<local>/p|.<Inapplicable(UNSTABLE_SMARTCAST): kotlin/String.length>#
|
||||
^ Int(123)
|
||||
}
|
||||
)
|
||||
R|<local>/p|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test2(x: R|kotlin/Any?|): R|kotlin/Unit| {
|
||||
lvar p: R|kotlin/Any?| = R|<local>/x|
|
||||
R|<local>/p|.<Unresolved name: length>#
|
||||
R|/run2|<R|kotlin/Int?|>(run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
R|<local>/p| = Null(null)
|
||||
^ R|/n|<R|kotlin/Int?|>()
|
||||
}
|
||||
, run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
(R|<local>/p| as R|kotlin/String|)
|
||||
^ Int(123)
|
||||
}
|
||||
)
|
||||
R|<local>/p|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
|
||||
R|<local>/p|?.{ $subj$.R|kotlin/String.length| }
|
||||
}
|
||||
public final fun test3(x: R|kotlin/Any?|): R|kotlin/Unit| {
|
||||
lvar p: R|kotlin/Any?| = R|<local>/x|
|
||||
R|<local>/p|.<Unresolved name: length>#
|
||||
R|/run2|<R|kotlin/Int?|>(run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
R|<local>/p| = Null(null)
|
||||
^ R|/n|<R|kotlin/Int?|>()
|
||||
}
|
||||
, run2@fun <anonymous>(): R|kotlin/Int?| <inline=NoInline, kind=EXACTLY_ONCE> {
|
||||
R|<local>/p| = String()
|
||||
^ Int(123)
|
||||
}
|
||||
)
|
||||
R|<local>/p|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
|
||||
R|<local>/p|?.{ $subj$.R|kotlin/String.length| }
|
||||
}
|
||||
Reference in New Issue
Block a user