FIR checker: differentiate UNSAFE_CALL from INAPPLICABLE_CANDIDATE

To do so, inside the root cause of inapplicable candidate errors,
we will record expected/actual type of receiver, if any.
That will help identifying inapplicable calls on nullable receiver.
This commit is contained in:
Jinseong Jeon
2021-01-26 16:03:27 -08:00
committed by Mikhail Glukhikh
parent 4b823eca21
commit e72ddbcbfe
275 changed files with 1426 additions and 1388 deletions
@@ -1,11 +1,11 @@
// !WITH_NEW_INFERENCE
fun foo() {
var v: String? = null
v.<!INAPPLICABLE_CANDIDATE!>length<!>
v.<!UNSAFE_CALL!>length<!>
v = "abc"
v.length
v = null
v.<!INAPPLICABLE_CANDIDATE!>length<!>
v.<!UNSAFE_CALL!>length<!>
v = "abc"
v.length
}
@@ -23,7 +23,7 @@ fun bar(s: String?) {
val hashCode = ss?.hashCode()
ss = null
if (hashCode != null) {
ss.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
ss.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -41,6 +41,6 @@ fun baz(arg: Some?) {
val ss = arg?.s
if (ss != null) {
arg.hashCode()
arg.s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
arg.s.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -37,7 +37,7 @@ fun test3() {
catch (e: B) {
return
}
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() // a is nullable here
a.<!UNSAFE_CALL!>hashCode<!>() // a is nullable here
}
fun test4() {
var a: Int? = null
@@ -50,7 +50,7 @@ fun test4() {
catch (e: B) {
return
}
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() // a is nullable here
a.<!UNSAFE_CALL!>hashCode<!>() // a is nullable here
}
fun test5() {
var a: Int?// = null
@@ -76,5 +76,5 @@ fun test6() {
finally {
a = null
}
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() // a is null here
a.<!UNSAFE_CALL!>hashCode<!>() // a is null here
}
@@ -2,7 +2,7 @@
fun foo() {
var v: String? = "xyz"
// It is possible in principle to provide smart cast here
v.<!INAPPLICABLE_CANDIDATE!>length<!>
v.<!UNSAFE_CALL!>length<!>
v = null
v.<!INAPPLICABLE_CANDIDATE!>length<!>
v.<!UNSAFE_CALL!>length<!>
}
@@ -12,7 +12,7 @@ fun foo(): Bar {
var y: Bar? = Bar()
while (x != null) {
// Here call is unsafe because of initialization and also inner loop
y.<!INAPPLICABLE_CANDIDATE!>next<!>()
y.<!UNSAFE_CALL!>next<!>()
while (y != null) {
if (x == y)
// x is not null because of outer while
@@ -12,7 +12,7 @@ operator fun Long?.inc() = this?.let { it + 1 }
fun bar(arg: Long?): Long {
var i = arg
if (i++ == 5L) {
return i<!INAPPLICABLE_CANDIDATE!>--<!> + i
return i<!UNSAFE_CALL!>--<!> + i
}
if (i++ == 7L) {
return i++ <!NONE_APPLICABLE!>+<!> i
@@ -3,6 +3,6 @@ operator fun Int?.inc(): Int? { return this }
public fun box(arg: Int?) : Int? {
var i : Int? = arg
var j = i++
j.<!INAPPLICABLE_CANDIDATE!>toInt<!>()
j.<!UNSAFE_CALL!>toInt<!>()
return i
}
@@ -9,5 +9,5 @@ public fun box() {
// type of j should be MyClass?
var j = ++i
// j is null so call should be unsafe
j.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
j.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -3,6 +3,6 @@ operator fun Int?.inc(): Int? { return this }
public fun box(arg: Int?) : Int? {
var i = arg
var j = ++i
j.<!INAPPLICABLE_CANDIDATE!>toInt<!>()
j.<!UNSAFE_CALL!>toInt<!>()
return ++j
}
@@ -10,5 +10,5 @@ fun foo() {
} catch (ex: Exception) {}
bar(s)
if (s != null) { }
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
s.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -6,5 +6,5 @@ fun foo() {
try {
s = null
} catch (ex: Exception) {}
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
s.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -12,5 +12,5 @@ fun foo() {
finally {
bar()
}
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
s.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -6,5 +6,5 @@ fun foo() {
try {
s = null
} catch (ex: Exception) {}
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
s.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -14,7 +14,7 @@ class MyClass {
var res = 0
m = create()
// See KT-7428
<!INAPPLICABLE_CANDIDATE!>for ((k, v) in m)
<!UNSAFE_CALL!>for ((k, v) in m)
res += (k.length + v.length)<!>
return res
}
@@ -2,5 +2,5 @@
fun foo(): Int {
var s: String? = "abc"
s = null
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
return s.<!UNSAFE_CALL!>length<!>
}