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:
committed by
Mikhail Glukhikh
parent
4b823eca21
commit
e72ddbcbfe
@@ -15,7 +15,7 @@ fun test2() {
|
||||
catch (e: ExcB) {
|
||||
10
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -28,7 +28,7 @@ fun test3() {
|
||||
catch (e: ExcB) {
|
||||
return
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
@@ -41,7 +41,7 @@ fun test4() {
|
||||
finally {
|
||||
""
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test5() {
|
||||
@@ -54,7 +54,7 @@ fun test5() {
|
||||
finally {
|
||||
return
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test6() {
|
||||
@@ -67,7 +67,7 @@ fun test6() {
|
||||
catch (e: ExcB) {
|
||||
return
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test7() {
|
||||
@@ -80,7 +80,7 @@ fun test7() {
|
||||
catch (e: ExcB) {
|
||||
""
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test8() {
|
||||
@@ -89,7 +89,7 @@ fun test8() {
|
||||
} catch (e: ExcA) {
|
||||
null
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test9() {
|
||||
|
||||
+10
-10
@@ -13,11 +13,11 @@ fun test0(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ fun test1(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -51,11 +51,11 @@ fun test2(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -69,11 +69,11 @@ fun test3(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -91,11 +91,11 @@ fun test5(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>()
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@ fun test1(s: String?) {
|
||||
catch (e: Exception) {
|
||||
requireNotNull(s)
|
||||
}
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>()
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
t2.<!UNSAFE_CALL!>not<!>()
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ fun test5(s: String?) {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s: String?) {
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@ fun test1(s: String?) {
|
||||
catch (e: Exception) {
|
||||
requireNotNull(s)
|
||||
}
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>()
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
t2.<!UNSAFE_CALL!>not<!>()
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ fun test5(s: String?) {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s: String?) {
|
||||
|
||||
+13
-13
@@ -13,15 +13,15 @@ fun test1() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
x.<!UNSAFE_CALL!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
// With old DFA of try/catch info about unsound smartcasts after try
|
||||
@@ -33,12 +33,12 @@ fun test2() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
finally {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -49,7 +49,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
s1.length
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -97,10 +97,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s1.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s1.<!UNSAFE_CALL!>length<!>
|
||||
s2.length
|
||||
}
|
||||
Vendored
+13
-13
@@ -14,15 +14,15 @@ fun test1() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
x.<!UNSAFE_CALL!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
// With old DFA of try/catch info about unsound smartcasts after try
|
||||
@@ -35,12 +35,12 @@ fun test2() {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
// BAD
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
finally {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -51,7 +51,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
s1.length
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -99,10 +99,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s1.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s1.<!UNSAFE_CALL!>length<!>
|
||||
s2.length
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user