FIR checker: report UNSAFE_CALL for overloaded function calls

Previously if an unsafe call is to an overloaded function, FIR checkers
report NONE_APPLICABLE. This change instead report them as UNSAFE_CALL
or its variants.
This commit is contained in:
Tianyu Geng
2021-04-09 21:26:07 +03:00
committed by Mikhail Glukhikh
parent 92df1f575a
commit 454ae3b17a
30 changed files with 83 additions and 142 deletions
@@ -6,9 +6,9 @@ class A() {
fun f(): Unit {
var x: Int? = 1
x = null
x <!NONE_APPLICABLE!>+<!> 1
x <!NONE_APPLICABLE!>plus<!> 1
x <!NONE_APPLICABLE!><<!> 1
x <!UNSAFE_OPERATOR_CALL!>+<!> 1
x <!UNSAFE_CALL!>plus<!> 1
x <!UNSAFE_OPERATOR_CALL!><<!> 1
x <!UNRESOLVED_REFERENCE!>+=<!> 1
x == 1
@@ -22,7 +22,7 @@ fun f(): Unit {
x === 1
x !== 1
x<!NONE_APPLICABLE!>..<!>2
x<!UNSAFE_OPERATOR_CALL!>..<!>2
<!ARGUMENT_TYPE_MISMATCH!>x<!> in 1..2
val y : Boolean? = true
+6 -6
View File
@@ -44,7 +44,7 @@ fun test() {
if (out == null || out.println(0) == Unit) {
out?.println(1)
out.<!NONE_APPLICABLE!>println<!>(1)
out<!UNSAFE_CALL!>.<!>println(1)
}
else {
out.println(2)
@@ -66,11 +66,11 @@ fun test() {
if (1 == 2 || out != null && out.println(1) == Unit) {
out?.println(2);
out.<!NONE_APPLICABLE!>println<!>(2);
out<!UNSAFE_CALL!>.<!>println(2);
}
else {
out?.println(3)
out.<!NONE_APPLICABLE!>println<!>(3)
out<!UNSAFE_CALL!>.<!>println(3)
}
out?.println()
@@ -103,7 +103,7 @@ fun test() {
if (out == null || out.println(0) == Unit) {
out?.println(1)
out.<!NONE_APPLICABLE!>println<!>(1)
out<!UNSAFE_CALL!>.<!>println(1)
}
else {
out.println(2)
@@ -127,11 +127,11 @@ fun test() {
if (1 == 2 || out != null && out.println(1) == Unit) {
out?.println(2);
out.<!NONE_APPLICABLE!>println<!>(2);
out<!UNSAFE_CALL!>.<!>println(2);
}
else {
out?.println(3)
out.<!NONE_APPLICABLE!>println<!>(3)
out<!UNSAFE_CALL!>.<!>println(3)
}
if (1 > 2) {
@@ -1,41 +0,0 @@
// !WITH_NEW_INFERENCE
class A() {
operator infix fun plus(i : Int) {}
operator fun unaryMinus() {}
operator infix fun contains(a : Any?) : Boolean = true
}
operator infix fun A.div(i : Int) {}
operator infix fun A?.times(i : Int) {}
fun test(x : Int?, a : A?) {
x.<!NONE_APPLICABLE!>plus<!>(1)
x?.plus(1)
x <!NONE_APPLICABLE!>+<!> 1
<!UNSAFE_CALL!>-<!>x
x<!UNSAFE_CALL!>.<!>unaryMinus()
x?.unaryMinus()
a<!UNSAFE_CALL!>.<!>plus(1)
a?.plus(1)
a <!UNSAFE_INFIX_CALL!>plus<!> 1
a <!UNSAFE_OPERATOR_CALL!>+<!> 1
<!UNSAFE_CALL!>-<!>a
a<!UNSAFE_CALL!>.<!>unaryMinus()
a?.unaryMinus()
a<!UNSAFE_CALL!>.<!>div(1)
a <!UNSAFE_OPERATOR_CALL!>/<!> 1
a <!UNSAFE_INFIX_CALL!>div<!> 1
a?.div(1)
a.times(1)
a * 1
a times 1
a?.times(1)
1 <!UNSAFE_OPERATOR_CALL!>in<!> a
a <!UNSAFE_INFIX_CALL!>contains<!> 1
a<!UNSAFE_CALL!>.<!>contains(1)
a?.contains(1)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
class A() {
operator infix fun plus(i : Int) {}
@@ -2,7 +2,7 @@ fun test() {
val out : Int? = null
val x : Nothing? = null
if (out != x)
out.<!NONE_APPLICABLE!>plus<!>(1)
out<!UNSAFE_CALL!>.<!>plus(1)
if (out == x) return
out.<!NONE_APPLICABLE!>plus<!>(1)
out<!UNSAFE_CALL!>.<!>plus(1)
}
@@ -16,7 +16,7 @@ fun foo() {
val y: Int? = 0
val z: Int? = 0
bar(<!ARGUMENT_TYPE_MISMATCH!>if (y != null) y else z<!>, <!ARGUMENT_TYPE_MISMATCH!>y<!>)
y <!NONE_APPLICABLE!>+<!> 2
y <!UNSAFE_OPERATOR_CALL!>+<!> 2
baz(<!ARGUMENT_TYPE_MISMATCH!>y<!>, <!ARGUMENT_TYPE_MISMATCH!>y<!>, if (y == null) return else y, y)
baz(y, z!!, z, y)
}
@@ -6,11 +6,11 @@ package example
fun test() {
val p = test.Public()
if (p.public is Int) p.public + 1
if (p.<!HIDDEN!>protected<!> is Int) p.<!HIDDEN!>protected<!> <!NONE_APPLICABLE!>+<!> 1
if (p.<!HIDDEN!>protected<!> is Int) p.<!HIDDEN!>protected<!> <!UNSAFE_OPERATOR_CALL!>+<!> 1
if (p.internal is Int) p.internal + 1
val i = test.Internal()
if (i.public is Int) i.public + 1
if (i.<!HIDDEN!>protected<!> is Int) i.<!HIDDEN!>protected<!> <!NONE_APPLICABLE!>+<!> 1
if (i.<!HIDDEN!>protected<!> is Int) i.<!HIDDEN!>protected<!> <!UNSAFE_OPERATOR_CALL!>+<!> 1
if (i.internal is Int) i.internal + 1
}
@@ -13,15 +13,15 @@ class B {
fun f() {
a = A()
a.<!NONE_APPLICABLE!>f<!>(true)
takeInt(a.<!NONE_APPLICABLE!>f<!>(""))
a<!UNSAFE_CALL!>.<!>f(true)
takeInt(a<!UNSAFE_CALL!>.<!>f(""))
a.<!NONE_APPLICABLE!>f<!>()
}
fun g() {
takeInt(if (3 > 2) {
a = A()
a.<!NONE_APPLICABLE!>f<!>(true)
a<!UNSAFE_CALL!>.<!>f(true)
} else {
6
})
@@ -9,6 +9,6 @@ var a: A? = null
fun smartCastInterference(b: B) {
if (a != null) {
a.<!NONE_APPLICABLE!>foo<!>(b)
a<!UNSAFE_CALL!>.<!>foo(b)
}
}
@@ -1,19 +0,0 @@
// !WITH_NEW_INFERENCE
// KT-282 Nullability in extension functions and in binary calls
class Set {
operator fun contains(x : Int) : Boolean = true
}
operator fun Set?.plus(x : Int) : Int = 1
operator fun Int?.contains(x : Int) : Boolean = false
fun f(): Unit {
var set : Set? = null
val i : Int? = null
i <!NONE_APPLICABLE!>+<!> 1
set + 1
1 <!UNSAFE_OPERATOR_CALL!>in<!> set
1 in 2
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
// KT-282 Nullability in extension functions and in binary calls
@@ -23,13 +23,13 @@ fun testDataFlowInfo1(a: Int?, b: Int?) {
val c: Int = a ?: b!!
doInt(c)
// b is nullable if a != null
b <!NONE_APPLICABLE!>+<!> 1
b <!UNSAFE_OPERATOR_CALL!>+<!> 1
}
fun testDataFlowInfo2(a: Int?, b: Int?) {
doInt(a ?: b!!)
// b is nullable if a != null
b <!NONE_APPLICABLE!>+<!> 1
b <!UNSAFE_OPERATOR_CALL!>+<!> 1
}
fun testTypeMismatch(a: String?, b: Any) {
@@ -16,7 +16,7 @@ fun foo(): Int {
k.run()
val d: Int = c
// a is not null because of k constructor, but we do not know it
return a <!NONE_APPLICABLE!>+<!> d
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
}
else return -1
}
@@ -11,7 +11,7 @@ fun foo(): Int {
}
k.run()
val d: Int = c
return a <!NONE_APPLICABLE!>+<!> d
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
}
else return -1
}
@@ -15,7 +15,7 @@ fun foo(): Int {
}
k.run()
val d: Int = c
return a <!NONE_APPLICABLE!>+<!> d
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
}
else return -1
}
@@ -15,7 +15,7 @@ fun bar(arg: Long?): Long {
return i<!UNSAFE_CALL!>--<!> + i
}
if (i++ == 7L) {
return i++ <!NONE_APPLICABLE!>+<!> i
return i++ <!UNSAFE_OPERATOR_CALL!>+<!> i
}
return 0L
}
@@ -2,5 +2,5 @@
fun foo(): Int {
var i: Int? = 42
i = null
return i <!NONE_APPLICABLE!>+<!> 1
return i <!UNSAFE_OPERATOR_CALL!>+<!> 1
}