FIR DFA: smartcast variable to Nothing? on null assignment
In order to make resolution still work for members not available from `Nothing`, we track the type without `Nothing?` and use that for resolution instead.
This commit is contained in:
committed by
teamcityserver
parent
7e2f15f532
commit
4726dcce40
@@ -5,24 +5,24 @@ class A() {
|
||||
fun f(): Unit {
|
||||
var x: Int? = 1
|
||||
x = null
|
||||
x <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
x + 1
|
||||
x <!UNSAFE_INFIX_CALL!>plus<!> 1
|
||||
x <!UNSAFE_OPERATOR_CALL!><<!> 1
|
||||
x <!UNSAFE_OPERATOR_CALL!>+=<!> 1
|
||||
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1<!>
|
||||
|
||||
x == 1
|
||||
x != 1
|
||||
|
||||
<!EQUALITY_NOT_APPLICABLE!>A() == 1<!>
|
||||
|
||||
<!EQUALITY_NOT_APPLICABLE!>x === "1"<!>
|
||||
<!EQUALITY_NOT_APPLICABLE!>x !== "1"<!>
|
||||
x === "1"
|
||||
x !== "1"
|
||||
|
||||
x === 1
|
||||
x !== 1
|
||||
|
||||
x<!UNSAFE_OPERATOR_CALL!>..<!>2
|
||||
<!ARGUMENT_TYPE_MISMATCH!>x<!> in 1..2
|
||||
x..2
|
||||
x in 1..2
|
||||
|
||||
val y : Boolean? = true
|
||||
false || <!CONDITION_TYPE_MISMATCH!>y<!>
|
||||
|
||||
@@ -8,7 +8,7 @@ fun foo(): Int {
|
||||
if (x != null) return x
|
||||
|
||||
val y: Int? = null
|
||||
if (y == null) return if (y != null) y else y
|
||||
if (y == null) return <!RETURN_TYPE_MISMATCH!>if (y != null) y else y<!>
|
||||
|
||||
val z: Int? = null
|
||||
if (z != null) return if (z == null) z else z
|
||||
|
||||
Vendored
+9
-9
@@ -173,15 +173,15 @@ fun test() {
|
||||
if (get() === null) {}
|
||||
|
||||
if (x == null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode()
|
||||
x?.hashCode()
|
||||
}
|
||||
|
||||
if (x == null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1)
|
||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
||||
}
|
||||
|
||||
if (x == null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
|
||||
x?.test2()
|
||||
}
|
||||
|
||||
if (x == null) {
|
||||
@@ -189,15 +189,15 @@ fun test() {
|
||||
}
|
||||
|
||||
if (x === null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode()
|
||||
x?.hashCode()
|
||||
}
|
||||
|
||||
if (x === null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1)
|
||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
||||
}
|
||||
|
||||
if (x === null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
|
||||
x?.test2()
|
||||
}
|
||||
|
||||
if (x === null) {
|
||||
@@ -303,9 +303,9 @@ fun test() {
|
||||
if (get() === null) {}
|
||||
|
||||
if (x == null) {
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode()
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1)
|
||||
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
|
||||
x?.hashCode()
|
||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
||||
x?.test2()
|
||||
x.test2()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ fun foo(): String {
|
||||
var t: String? = "y"
|
||||
if (t == null) t = "x"
|
||||
var x: Int? = null
|
||||
if (x == null) x <!UNSAFE_OPERATOR_CALL!>+=<!> null
|
||||
if (x == null) <!ASSIGNMENT_TYPE_MISMATCH!>x += null<!>
|
||||
return t + s
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ fun String?.gav() {}
|
||||
fun bar(s: String?) {
|
||||
if (s != null) return
|
||||
s.gav()
|
||||
s <!USELESS_CAST!>as? String<!>
|
||||
s <!USELESS_CAST!>as String?<!>
|
||||
s as? String
|
||||
s as String?
|
||||
s as String
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// FILE: My.java
|
||||
|
||||
public class My {
|
||||
static public My create() { return new My(); }
|
||||
public void foo() {}
|
||||
}
|
||||
|
||||
// FILE: Test.kt
|
||||
|
||||
fun test() {
|
||||
val my = My.create()
|
||||
if (my == null) {
|
||||
my.foo()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: My.java
|
||||
|
||||
public class My {
|
||||
|
||||
@@ -7,14 +7,14 @@ class TestWithEquals {
|
||||
}
|
||||
|
||||
fun bar(i: Test?) {
|
||||
if (i == null) foo(<!ARGUMENT_TYPE_MISMATCH!>i<!>)
|
||||
if (i == null) foo(i)
|
||||
}
|
||||
|
||||
fun bar(i: TestWithEquals?) {
|
||||
if (i == null) foo(<!ARGUMENT_TYPE_MISMATCH!>i<!>)
|
||||
if (null == i) foo(<!ARGUMENT_TYPE_MISMATCH!>i<!>)
|
||||
if (i == null) foo(i)
|
||||
if (null == i) foo(i)
|
||||
when (i) {
|
||||
null -> foo(<!ARGUMENT_TYPE_MISMATCH!>i<!>)
|
||||
null -> foo(i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,4 @@ fun gav(i: TestWithEquals?, j: TestWithEquals?) {
|
||||
if (j == null) {
|
||||
if (i == j) foo(<!ARGUMENT_TYPE_MISMATCH!>i<!>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -19,11 +19,11 @@ fun g(x: B<Int>) {
|
||||
val y = x.content
|
||||
if (y == null) {
|
||||
f(y)
|
||||
g(y)
|
||||
<!NONE_APPLICABLE!>g<!>(y)
|
||||
}
|
||||
|
||||
if (y is Nothing?) {
|
||||
f(y)
|
||||
g(y)
|
||||
<!NONE_APPLICABLE!>g<!>(y)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fun foo(): Int {
|
||||
var i: Int? = 42
|
||||
i = null
|
||||
return i <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
return <!RETURN_TYPE_MISMATCH, TYPE_MISMATCH!>i + 1<!>
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ n: kotlin.Nothing, /*1*/ nn: kotlin.Nothing?): kotlin.Unit
|
||||
public fun test1(/*0*/ n: kotlin.Nothing): kotlin.Unit
|
||||
public fun test2(/*0*/ n: kotlin.Nothing?): kotlin.Unit
|
||||
public fun test3(/*0*/ n: kotlin.Nothing?): kotlin.Unit
|
||||
|
||||
|
||||
Reference in New Issue
Block a user