FIR: report UNSAFE_CALL on dot when possible
This commit is contained in:
+2
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
fun testIsNullOrBlank(x: String?) {
|
||||
if (x.isNullOrBlank()) {
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
else {
|
||||
x.length
|
||||
@@ -15,6 +15,6 @@ fun testIsNotNullOrBlank(x: String?) {
|
||||
x.length
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
fun testIsNullOrEmpty(x: String?) {
|
||||
if (x.isNullOrEmpty()) {
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
else {
|
||||
x.length
|
||||
@@ -15,6 +15,6 @@ fun testIsNotNullOrEmpty(x: String?) {
|
||||
x.length
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@ fun nullWhenNull(x: Int?): Int? {
|
||||
|
||||
fun testNullWhenNull(x: Int?) {
|
||||
if (nullWhenNull(x) == null) {
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
else {
|
||||
x.dec()
|
||||
@@ -24,10 +24,10 @@ fun testNullWhenNull(x: Int?) {
|
||||
x.dec()
|
||||
}
|
||||
else {
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
// NB. it is the same function as `nullWhenNull`, but annotations specifies other facet of the function behaviour
|
||||
@@ -43,15 +43,15 @@ fun testNotNullWhenNotNull (x: Int?) {
|
||||
x == null
|
||||
}
|
||||
else {
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
if (notNullWhenNotNull(x) != null) {
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
else {
|
||||
x == null
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,28 +20,28 @@ fun myEqualsNotNull(x: Int?): Boolean {
|
||||
}
|
||||
|
||||
fun testBasicEquals(x: Int?) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
|
||||
if (myEqualsNull(x)) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
x.inc()
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
fun testBasicNotEquals(x: Int?) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
|
||||
if (myEqualsNotNull(x)) {
|
||||
x.inc()
|
||||
}
|
||||
else {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ fun Any?.isNull(): Boolean {
|
||||
|
||||
fun smartcastOnReceiver(x: Int?) {
|
||||
if (x.isNull()) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
x.dec()
|
||||
@@ -26,10 +26,10 @@ class UnstableReceiver {
|
||||
|
||||
fun smartcastOnUnstableReceiver() {
|
||||
if (x.isNull()) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
x.<!UNSAFE_CALL!>dec<!>()
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ import kotlin.contracts.*
|
||||
|
||||
fun f3(value: String?) {
|
||||
if (!value.isNullOrEmpty() is Boolean) {
|
||||
value.<!UNSAFE_CALL!>length<!>
|
||||
value<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
val foo = iterator {
|
||||
yield(0)
|
||||
val nullable: String? = null
|
||||
nullable.<!UNSAFE_CALL!>length<!>
|
||||
nullable.<!UNSAFE_CALL!>get<!>(2)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
val foo = iterator {
|
||||
yield(0)
|
||||
val nullable: String? = null
|
||||
|
||||
Vendored
+1
-1
@@ -87,7 +87,7 @@ fun test() {
|
||||
this@with.<!UNRESOLVED_REFERENCE!>yield<!>("")
|
||||
|
||||
yield2("")
|
||||
this@with.<!UNSAFE_CALL!>yield2<!>("")
|
||||
this@with<!UNSAFE_CALL!>.<!>yield2("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
// KT-9051: Allow smart cast for captured variables if they are not modified
|
||||
|
||||
fun foo(y: String?) {
|
||||
var x: String? = null
|
||||
y?.let { x = it }
|
||||
x.<!UNSAFE_CALL!>length<!> // Smart cast is not possible
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// KT-9051: Allow smart cast for captured variables if they are not modified
|
||||
|
||||
fun foo(y: String?) {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun bar(z: String?) = z
|
||||
fun foo(y: String?) {
|
||||
var x: String? = ""
|
||||
if (x != null) {
|
||||
bar(y?.let { x = null; it }).<!UNSAFE_CALL!>length<!>
|
||||
bar(y?.let { x = null; it })<!UNSAFE_CALL!>.<!>length
|
||||
x.length // Smart cast is not possible
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ fun foo(y: String?) {
|
||||
var x: String? = ""
|
||||
if (x != null) {
|
||||
with(y?.let { x = null; it }) {
|
||||
this.<!UNSAFE_CALL!>length<!>
|
||||
this<!UNSAFE_CALL!>.<!>length
|
||||
x.length
|
||||
}
|
||||
x.length
|
||||
|
||||
@@ -15,7 +15,7 @@ fun test2() {
|
||||
catch (e: ExcB) {
|
||||
10
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -28,7 +28,7 @@ fun test3() {
|
||||
catch (e: ExcB) {
|
||||
return
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
@@ -41,7 +41,7 @@ fun test4() {
|
||||
finally {
|
||||
""
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test5() {
|
||||
@@ -54,7 +54,7 @@ fun test5() {
|
||||
finally {
|
||||
return
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test6() {
|
||||
@@ -67,7 +67,7 @@ fun test6() {
|
||||
catch (e: ExcB) {
|
||||
return
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test7() {
|
||||
@@ -80,7 +80,7 @@ fun test7() {
|
||||
catch (e: ExcB) {
|
||||
""
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test8() {
|
||||
@@ -89,7 +89,7 @@ fun test8() {
|
||||
} catch (e: ExcA) {
|
||||
null
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test9() {
|
||||
|
||||
+10
-10
@@ -13,11 +13,11 @@ fun test0(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
y<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ fun test1(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
y<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -51,11 +51,11 @@ fun test2(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
y<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -69,11 +69,11 @@ fun test3(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
y<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
@@ -91,11 +91,11 @@ fun test5(x: Int?) {
|
||||
|
||||
if (x != null) {
|
||||
x.inc()
|
||||
y.<!UNSAFE_CALL!>inc<!>()
|
||||
y<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
x.<!UNSAFE_CALL!>inc<!>()
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
y.inc()
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@ fun test1(s: String?) {
|
||||
catch (e: Exception) {
|
||||
requireNotNull(s)
|
||||
}
|
||||
t2.<!UNSAFE_CALL!>not<!>()
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
t2<!UNSAFE_CALL!>.<!>not()
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ fun test5(s: String?) {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>not<!>()
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
t2<!UNSAFE_CALL!>.<!>not()
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ fun test5(s: String?) {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test6(s: String?) {
|
||||
|
||||
+14
-14
@@ -13,15 +13,15 @@ fun test1() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
finally {
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -49,7 +49,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
t2<!UNSAFE_CALL!>.<!>not() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
t2<!UNSAFE_CALL!>.<!>not() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
s2<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
s1.length
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
s2<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -97,10 +97,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s1.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNSAFE_CALL!>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.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
finally {
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
x.<!UNSAFE_CALL!>length<!>
|
||||
x<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -51,7 +51,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
t2<!UNSAFE_CALL!>.<!>not() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!UNSAFE_CALL!>not<!>() // wrong smartcast, NPE
|
||||
t2<!UNSAFE_CALL!>.<!>not() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
s2<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
s1.length
|
||||
s2.<!UNSAFE_CALL!>length<!>
|
||||
s2<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -99,10 +99,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!UNSAFE_CALL!>length<!>
|
||||
s1.<!UNSAFE_CALL!>length<!>
|
||||
s<!UNSAFE_CALL!>.<!>length
|
||||
s1<!UNSAFE_CALL!>.<!>length
|
||||
s2.length
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user