[FIR] Support PreliminaryLoopVisitor in FIR DFA
This commit is contained in:
@@ -10,5 +10,5 @@ fun use() {
|
||||
// Write to x is AFTER
|
||||
x.hashCode()
|
||||
// No smart cast should be here!
|
||||
foo(bar { x = null }, x.hashCode())
|
||||
foo(bar { x = null }, x<!UNSAFE_CALL!>.<!>hashCode())
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ fun foo(arg: Int?) {
|
||||
if (x == null) return
|
||||
run {
|
||||
// Unsafe because of owner modification
|
||||
x.hashCode()
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
x = null
|
||||
}
|
||||
if (x != null) x = 42
|
||||
// Unsafe because of lambda
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ fun foo(x: Int, f: () -> Unit, y: Int) {}
|
||||
fun bar() {
|
||||
var x: Int?
|
||||
x = 4
|
||||
foo(x, { x = null; x<!UNSAFE_CALL!>.<!>hashCode() }, x)
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(x, { x = null; x<!UNSAFE_CALL!>.<!>hashCode() }, x)
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@ public fun foo() {
|
||||
var i: Any = 1
|
||||
if (i is Int) {
|
||||
while (i != 10) {
|
||||
i++ // Here smart cast should not be performed due to a successor
|
||||
i<!UNRESOLVED_REFERENCE!>++<!> // Here smart cast should not be performed due to a successor
|
||||
i = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ public fun foo() {
|
||||
var i: Any = 1
|
||||
if (i is Int) {
|
||||
while (i != 10) {
|
||||
i++
|
||||
i<!UNRESOLVED_REFERENCE!>++<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,5 +13,5 @@ fun list(start: String) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can never be null but we do not know it
|
||||
e.hashCode()
|
||||
}
|
||||
e<!UNSAFE_CALL!>.<!>hashCode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ fun foo(): Bar {
|
||||
y = Bar()
|
||||
while (x != null) {
|
||||
// Here call is unsafe because of inner loop
|
||||
y.next()
|
||||
y<!UNSAFE_CALL!>.<!>next()
|
||||
while (y != null) {
|
||||
if (x == y)
|
||||
// x is not null because of outer while
|
||||
@@ -25,4 +25,4 @@ fun foo(): Bar {
|
||||
x = x.next()
|
||||
}
|
||||
return Bar()
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
-4
@@ -30,7 +30,7 @@ fun baz(s: String?) {
|
||||
x.hashCode()
|
||||
}
|
||||
run {
|
||||
x.hashCode()
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
x = null
|
||||
}
|
||||
}
|
||||
@@ -40,11 +40,11 @@ fun gaz(s: String?) {
|
||||
var x = s
|
||||
if (x != null) {
|
||||
run {
|
||||
x.hashCode()
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
x = null
|
||||
}
|
||||
run {
|
||||
x.hashCode()
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,4 +57,4 @@ fun gav(s: String?) {
|
||||
}
|
||||
x = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething(): Boolean = true
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject) {
|
||||
var e: SomeObject?
|
||||
e = start
|
||||
do {
|
||||
// In theory smart cast is possible here
|
||||
// But in practice we have a loop with changing e
|
||||
// ?: should we "or" entrance type info with condition type info?
|
||||
if (!e.doSomething())
|
||||
break
|
||||
// Smart cast here is still not possible
|
||||
e = e.next()
|
||||
} while (e != null)
|
||||
// e can be null because of next()
|
||||
e.doSomething()
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething(): Boolean = true
|
||||
fun next(): SomeObject? = n
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(pp: String?): Int {
|
||||
var p = pp
|
||||
do {
|
||||
p!!.length
|
||||
if (p == "abc") break
|
||||
p = null
|
||||
} while (!x())
|
||||
// Smart cast is NOT possible here
|
||||
return p.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(pp: String?): Int {
|
||||
|
||||
@@ -9,9 +9,9 @@ fun list(start: SomeObject): SomeObject {
|
||||
var e: SomeObject? = start
|
||||
for (i in 0..42) {
|
||||
// Unsafe calls because of nullable e at the beginning
|
||||
e.doSomething()
|
||||
e = e.next()
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
e = e<!UNSAFE_CALL!>.<!>next()
|
||||
}
|
||||
// Smart cast is not possible here due to next()
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,5 +16,5 @@ fun list(start: SomeObject) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e.doSomething()
|
||||
}
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@ public fun foo() {
|
||||
var i: Int? = 1
|
||||
if (i != null) {
|
||||
while (i != 10) {
|
||||
i++ // Here smart cast should not be performed due to a successor
|
||||
i<!UNSAFE_CALL!>++<!> // Here smart cast should not be performed due to a successor
|
||||
i = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ public fun foo() {
|
||||
var i: Int? = 1
|
||||
if (i != null) {
|
||||
while (i != 10) {
|
||||
i++
|
||||
i<!UNSAFE_CALL!>++<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,5 +13,5 @@ fun list(start: SomeObject) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e.doSomething()
|
||||
}
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user