[FIR] Support PreliminaryLoopVisitor in FIR DFA

This commit is contained in:
Dmitriy Novozhilov
2021-02-11 17:42:30 +03:00
parent 0e46a961a3
commit 5711a8d610
34 changed files with 294 additions and 106 deletions
@@ -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())
}
@@ -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()
}
}
@@ -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,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,7 +2,7 @@ public fun foo() {
var i: Any = 1
if (i is Int) {
while (i != 10) {
i++
i<!UNRESOLVED_REFERENCE!>++<!>
}
}
}
}
@@ -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()
}
@@ -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()
}
}
@@ -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
}
}
}
@@ -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
@@ -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,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
}
}
@@ -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,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,7 +2,7 @@ public fun foo() {
var i: Int? = 1
if (i != null) {
while (i != 10) {
i++
i<!UNSAFE_CALL!>++<!>
}
}
}
}
@@ -13,5 +13,5 @@ fun list(start: SomeObject) {
e = e.next()
}
// e can be null because of next()
e.doSomething()
}
e<!UNSAFE_CALL!>.<!>doSomething()
}