FIR DFA: fix logic clear aliasing
The logic should clear back aliases as well. To ensure all back aliases don't lose any information, statements on the original variable are copied over to its aliases.
This commit is contained in:
committed by
teamcityserver
parent
e495c722c7
commit
7e2f15f532
@@ -0,0 +1,65 @@
|
||||
fun test() {
|
||||
var a: Any? = null
|
||||
var b = a
|
||||
var c = b
|
||||
// Now both `b` and `c` are aliases of `a`.
|
||||
|
||||
if (a is String) {
|
||||
b.length // OK
|
||||
c.length // OK
|
||||
}
|
||||
if (b is String) {
|
||||
a.length // OK
|
||||
c.length // OK
|
||||
}
|
||||
if (c is String) {
|
||||
a.length // OK
|
||||
b.length // OK
|
||||
}
|
||||
|
||||
b = 3 // break `b` -> `a`
|
||||
if (a is String) {
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.length // OK, since `c` is aliased to `a`
|
||||
}
|
||||
if (b is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (c is String) {
|
||||
a.length // OK, since `c` is alised to `a`
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
|
||||
a = 2 // break `c` -> `a`
|
||||
if (a is String) {
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (b is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (c is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
|
||||
c = b // create aliasing `c` -> `b`
|
||||
c.unaryPlus() // OK due to aliasing
|
||||
b = ""
|
||||
c.unaryPlus() // OK since `c` should carry all typing information that was on `b` before `b = ""`.
|
||||
|
||||
c = ""
|
||||
c.length // OK
|
||||
c.<!UNRESOLVED_REFERENCE!>unaryPlus<!>() // error
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
var a: Any? = null
|
||||
a = ""
|
||||
var b = a
|
||||
a = 3
|
||||
b.length // OK
|
||||
b.<!UNRESOLVED_REFERENCE!>unaryPlus<!>() // error
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
fun test() {
|
||||
var a: Any? = null
|
||||
var b = a
|
||||
var c = b
|
||||
// Now both `b` and `c` are aliases of `a`.
|
||||
|
||||
if (a is String) {
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
}
|
||||
if (b is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
}
|
||||
if (c is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // OK
|
||||
}
|
||||
|
||||
b = 3 // break `b` -> `a`
|
||||
if (a is String) {
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // OK, since `c` is aliased to `a`
|
||||
}
|
||||
if (<!USELESS_IS_CHECK!>b is String<!>) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (c is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // OK, since `c` is alised to `a`
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
|
||||
a = 2 // break `c` -> `a`
|
||||
if (<!USELESS_IS_CHECK!>a is String<!>) {
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (<!USELESS_IS_CHECK!>b is String<!>) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
c.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
if (c is String) {
|
||||
a.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
b.<!UNRESOLVED_REFERENCE!>length<!> // error
|
||||
}
|
||||
|
||||
c = b // create aliasing `c` -> `b`
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.unaryPlus() // OK due to aliasing
|
||||
b = ""
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.unaryPlus() // OK since `c` should carry all typing information that was on `b` before `b = ""`.
|
||||
|
||||
c = ""
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.length // OK
|
||||
c.<!UNRESOLVED_REFERENCE!>unaryPlus<!>() // error
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
var a: Any? = <!VARIABLE_WITH_REDUNDANT_INITIALIZER!>null<!>
|
||||
a = ""
|
||||
var b = a
|
||||
a = 3
|
||||
<!DEBUG_INFO_SMARTCAST!>b<!>.length // OK
|
||||
b.<!UNRESOLVED_REFERENCE!>unaryPlus<!>() // error
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
public fun test2(): kotlin.Unit
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun foo() {
|
||||
val y = x
|
||||
x = null
|
||||
if (y != null) {
|
||||
x.hashCode()
|
||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ operator fun Long?.inc() = this?.let { it + 1 }
|
||||
fun bar(arg: Long?): Long {
|
||||
var i = arg
|
||||
if (i++ == 5L) {
|
||||
return i<!UNSAFE_CALL!>--<!> + i
|
||||
return i<!UNSAFE_CALL!>--<!> <!UNSAFE_OPERATOR_CALL!>+<!> i
|
||||
}
|
||||
if (i++ == 7L) {
|
||||
return i++ <!UNSAFE_OPERATOR_CALL!>+<!> i
|
||||
|
||||
Reference in New Issue
Block a user