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
+3 -3
View File
@@ -29,7 +29,7 @@ class C {
while (a == null) {
break;
}
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
a.<!UNSAFE_CALL!>compareTo<!>("2")
}
fun notContainsBreak(a: String?, b: String?) {
@@ -70,7 +70,7 @@ class C {
break@l
}
}
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
a.<!UNSAFE_CALL!>compareTo<!>("2")
}
fun unresolvedBreak(a: String?, array: Array<Int>) {
@@ -80,7 +80,7 @@ class C {
}
if (true) break else <!NOT_A_LOOP_LABEL!>break@l<!>
}
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
a.<!UNSAFE_CALL!>compareTo<!>("2")
}
fun twoLabelsOnLoop() {
+1 -1
View File
@@ -158,7 +158,7 @@ fun test() {
fun f(out : String?) {
out?.get(0)
out.<!INAPPLICABLE_CANDIDATE!>get<!>(0)
out.<!UNSAFE_CALL!>get<!>(0)
if (out != null) else return;
out.get(0)
}
@@ -14,11 +14,11 @@ fun test() {
}
fun check() {
[1, 2] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() }
[""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() }
[1, 2] <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() }
[""] <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() }
val f: IntArray = [1]
[f] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() }
[f] <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() }
[1, ""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() }
[1, ""] <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() }
}
@@ -7,9 +7,9 @@ operator fun <K> Container<K>.iterator(): Iterator<K> = null!!
fun test() {
val container: Container<String>? = null
// Error
container.<!INAPPLICABLE_CANDIDATE!>iterator<!>()
container.<!UNSAFE_CALL!>iterator<!>()
// for extension iterator, this code compiles, but should not
<!INAPPLICABLE_CANDIDATE!>for (s in container) {}<!>
<!UNSAFE_CALL!>for (s in container) {}<!>
}
class OtherContainer<K>(val k: K) {
operator fun iterator(): Iterator<K> = null!!
@@ -18,5 +18,5 @@ class OtherContainer<K>(val k: K) {
fun test2() {
val other: OtherContainer<String>? = null
// Error
<!INAPPLICABLE_CANDIDATE!>for (s in other) {}<!>
<!UNSAFE_CALL!>for (s in other) {}<!>
}
@@ -8,7 +8,7 @@ class It {
}
fun test(c: Coll?) {
<!INAPPLICABLE_CANDIDATE!>for (x in c) {}<!>
<!UNSAFE_CALL!>for (x in c) {}<!>
if (c != null) {
for(x in c) {}
@@ -8,5 +8,5 @@ class It {
}
fun test() {
<!INAPPLICABLE_CANDIDATE, INAPPLICABLE_CANDIDATE!>for (x in Coll()) {}<!>
<!UNSAFE_CALL, UNSAFE_CALL!>for (x in Coll()) {}<!>
}
@@ -8,7 +8,7 @@ operator fun <T> Data<T>.component2() = y
fun foo(): Int {
val d: Data<Int>? = null
// An error must be here
val (<!INAPPLICABLE_CANDIDATE!>x<!>, <!INAPPLICABLE_CANDIDATE!>y<!>) = d
val (x, y) = <!COMPONENT_FUNCTION_ON_NULLABLE, COMPONENT_FUNCTION_ON_NULLABLE!>d<!>
return x + y
}
@@ -17,6 +17,6 @@ data class NormalData<T>(val x: T, val y: T)
fun bar(): Int {
val d: NormalData<Int>? = null
// An error must be here
val (<!INAPPLICABLE_CANDIDATE!>x<!>, <!INAPPLICABLE_CANDIDATE!>y<!>) = d
val (x, y) = <!COMPONENT_FUNCTION_ON_NULLABLE, COMPONENT_FUNCTION_ON_NULLABLE!>d<!>
return x + y
}
@@ -10,6 +10,6 @@ fun test(a: Any?, flag: Boolean, x: Any?) {
}
else {
b = x
b.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
b.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -4,11 +4,11 @@ fun baz(b: Boolean): Boolean = !b
fun foo() {
val x: Int? = null
bar(<!INAPPLICABLE_CANDIDATE!>-<!>x)
bar(<!UNSAFE_CALL!>-<!>x)
if (x != null) bar(-x)
bar(<!INAPPLICABLE_CANDIDATE!>-<!>x)
bar(<!UNSAFE_CALL!>-<!>x)
val b: Boolean? = null
baz(<!INAPPLICABLE_CANDIDATE!>!<!>b)
baz(<!UNSAFE_CALL!>!<!>b)
if (b != null) baz(!b)
}
@@ -11,7 +11,7 @@ class MyClass2 {}
<!CONFLICTING_OVERLOADS!>fun MyClass2.component1()<!> = 1.3
fun test(mc1: MyClass, mc2: MyClass2) {
val (<!INAPPLICABLE_CANDIDATE!>a<!>, b) = <!COMPONENT_FUNCTION_MISSING!>mc1<!>
val (a, b) = <!COMPONENT_FUNCTION_MISSING!>mc1<!>
val (c) = mc2
//a,b,c are error types
@@ -5,7 +5,7 @@ fun foo(block: () -> (() -> Int)) {}
fun test() {
val x = <!EXPRESSION_REQUIRED!>fun named1(x: Int): Int { return 1 }<!>
x <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Int, Int>>() }
x <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Int, Int>>() }
foo { fun named2(): Int {return 1} }
foo({ fun named3() = 1 })
@@ -64,7 +64,7 @@ import outer.*
command.foo
command.<!INAPPLICABLE_CANDIDATE!>equals<!>(null)
command.<!UNSAFE_CALL!>equals<!>(null)
command?.equals(null)
command.equals1(null)
command?.equals1(null)
@@ -9,13 +9,13 @@ interface T {
}
fun test(t: T) {
t.<!INAPPLICABLE_CANDIDATE!>f<!>(1) //unsafe call error
t.<!UNSAFE_CALL!>f<!>(1) //unsafe call error
t.f?.invoke(1)
}
fun test1(t: T?) {
t.<!UNRESOLVED_REFERENCE!>f<!>(1) // todo resolve f as value and report UNSAFE_CALL
t?.<!INAPPLICABLE_CANDIDATE!>f<!>(1)
t.<!INAPPLICABLE_CANDIDATE!>f<!>?.invoke(1)
t?.<!UNSAFE_CALL!>f<!>(1)
t.<!UNSAFE_CALL!>f<!>?.invoke(1)
t?.f?.invoke(1)
}
@@ -8,7 +8,7 @@ fun <R> List<R>.a() {}
fun test1(i: Int?) {
1.<!INAPPLICABLE_CANDIDATE!>a<!>()
i.<!INAPPLICABLE_CANDIDATE!>a<!>()
i.<!UNSAFE_CALL!>a<!>()
}
fun <R> test2(c: Collection<R>) {
@@ -19,7 +19,7 @@ fun Int.foo() {}
fun test3(s: String?) {
"".<!INAPPLICABLE_CANDIDATE!>foo<!>()
s.<!INAPPLICABLE_CANDIDATE!>foo<!>()
s.<!UNSAFE_CALL!>foo<!>()
"".<!INAPPLICABLE_CANDIDATE!>foo<!>(1)
s.<!INAPPLICABLE_CANDIDATE!>foo<!>("a")
}
@@ -52,5 +52,5 @@ fun test7(l: List<String?>) {
}
fun test8(l: List<Any>?) {
l.<!INAPPLICABLE_CANDIDATE!>b<!>()
l.<!UNSAFE_CALL!>b<!>()
}
@@ -24,24 +24,24 @@ fun bar(aInstance: A, bInstance: B) {
foo(bInstance) {
(a, b): A, (c, d) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
foo(bInstance) {
(a, b), (c, d) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
foo<A, B>(bInstance) {
(a, b), (c, d) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
@@ -23,7 +23,7 @@ fun bar() {
}
foo { (a, b), (c, b) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
b checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { <!INAPPLICABLE_CANDIDATE!>_<!><B>() }
}
@@ -36,8 +36,8 @@ fun bar() {
}
foobar { (a, b), (c, d) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>b<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
@@ -32,12 +32,12 @@ fun bar() {
}
foobar { (a, b), (c, d) ->
<!UNRESOLVED_REFERENCE!>a<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
<!UNRESOLVED_REFERENCE!>a<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
d checkType { _<Short>() }
}
foobar { (a, b), (c, d) ->
<!UNRESOLVED_REFERENCE!>b<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>b<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
c checkType { _<Double>() }
}
}
@@ -20,7 +20,7 @@ class A : Outer<Double, Short>() {
fun foo() {
Derived().foo() checkType { _<Outer<String, Int>.Inner<Char>>() }
Derived().baz() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<Char, String>>() }
Derived().baz() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<Char, String>>() }
A.B().bar() checkType { _<Outer<Float, Long>.Inner<String>>() }
A.B().x() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<String, Float>>() }
A.B().x() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<String, Float>>() }
}
@@ -43,7 +43,7 @@ fun test() {
x = foobar<String>()
x().foo().a() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><A<String, Double, Short, Long>>() }
x().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<String, Double, Short, Char>>() }
x().bar() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<String, Double, Short, Char>>() }
x = foobar<Int>()
@@ -51,5 +51,5 @@ fun test() {
y = noParameters()
y().foo().a() checkType { _<A<Any, Double, Short, Long>>() }
y().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<Any, Double, Short, Char>>() }
y().bar() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<Any, Double, Short, Char>>() }
}
@@ -44,7 +44,7 @@ class Outer<T> {
x = foobar<String>()
x().foo().a() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, String, Double, Short, Long>>() }
x().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, String, Double, Short, Char>>() }
x().bar() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, String, Double, Short, Char>>() }
x = foobar<Int>()
x = z.foobar<String>()
@@ -53,7 +53,7 @@ class Outer<T> {
y = noParameters()
y().foo().a() checkType { _<A<T, F, Any, Double, Short, Long>>() }
y().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, Any, Double, Short, Char>>() }
y().bar() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, Any, Double, Short, Char>>() }
}
}
}
@@ -15,5 +15,5 @@ class Derived : BaseDerived2<Int>() {
fun foo() {
Derived().foo() checkType { _<Outer<Int, String>.Inner<Char>>() }
Derived().baz() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<Char, Int>>() }
Derived().baz() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Map<Char, Int>>() }
}
@@ -23,7 +23,7 @@ fun testNoSmartCast1(s: String?) {
if (s != null) ""
else noSmartCast1(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
s.<!UNSAFE_CALL!>length<!>
}
fun testNoSmartCast2(s: String?) {
@@ -31,7 +31,7 @@ fun testNoSmartCast2(s: String?) {
if (s != null) ( {""} )
else noSmartCast2(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
s.<!UNSAFE_CALL!>length<!>
}
fun testNoSmartCast3(s: String?) {
@@ -39,7 +39,7 @@ fun testNoSmartCast3(s: String?) {
if (s != null) ""
else noSmartCast3(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
s.<!UNSAFE_CALL!>length<!>
}
// KT-36069
@@ -48,5 +48,5 @@ fun testNoSmartCast4(s: String?) {
if (s != null) ( {""} )
else noSmartCast4(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
s.<!UNSAFE_CALL!>length<!>
}
@@ -3,14 +3,14 @@ package c
interface A<T>
fun test(a: A<Int>?) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() //no error
a.<!UNSAFE_CALL!>foo<!>() //no error
}
fun <R> A<R>.foo() {}
//------------
fun test(nullabilityInfoMap: Map<Int, Any>?) {
nullabilityInfoMap.<!INAPPLICABLE_CANDIDATE!>iterator<!>() //no error
nullabilityInfoMap.<!UNSAFE_CALL!>iterator<!>() //no error
}
//resolves to
@@ -20,7 +20,7 @@ public fun <K,V> Map<K,V>.iterator(): Iterator<Map.Entry<K,V>> {}
//-------------
fun foo() : Boolean {
val nullableList = getNullableList()
return nullableList.<!INAPPLICABLE_CANDIDATE!>contains<!>("")
return nullableList.<!UNSAFE_CALL!>contains<!>("")
}
@@ -19,9 +19,9 @@ public abstract class CollectionWithSize implements java.util.Collection<String>
// FILE: main.kt
fun main(c: CollectionWithSize) {
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
}
@@ -20,9 +20,9 @@ public abstract class CollectionWithSize implements java.util.Collection<String>
// FILE: main.kt
fun main(c: CollectionWithSize) {
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
}
@@ -19,9 +19,9 @@ public abstract class CollectionWithSize implements java.util.Collection<String>
// FILE: main.kt
fun main(c: CollectionWithSize) {
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
CompressionType.ZIP.<!AMBIGUITY!>name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Double>() }
c.<!AMBIGUITY!>size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
<!UNRESOLVED_REFERENCE!>CompressionType.ZIP::name<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<Double>>() }
<!UNRESOLVED_REFERENCE!>c::size<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><kotlin.reflect.KProperty0<String>>() }
}
@@ -17,12 +17,12 @@ public interface J2 extends J {
// FILE: main.kt
fun main() {
<!INAPPLICABLE_CANDIDATE!>J<!> { s: String -> s} // should be prohibited, because SAM value parameter has nullable type
J { "" + it.<!INAPPLICABLE_CANDIDATE!>length<!> }
J { "" + it.<!UNSAFE_CALL!>length<!> }
J { null }
J { it?.length?.toString() }
<!INAPPLICABLE_CANDIDATE!>J2<!> { s: String -> s}
J2 { "" + it.<!INAPPLICABLE_CANDIDATE!>length<!> }
J2 { "" + it.<!UNSAFE_CALL!>length<!> }
J2 { null }
J2 { it?.length?.toString() }
}
@@ -11,6 +11,6 @@ public class A {
// FILE: main.kt
fun foo(a: A) {
a.<!AMBIGUITY!>foo<!>() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
A.<!AMBIGUITY!>bar<!>() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
a.<!AMBIGUITY!>foo<!>() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
A.<!AMBIGUITY!>bar<!>() <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
}
@@ -12,21 +12,21 @@ fun test(x : Int?, a : A?) {
x.<!NONE_APPLICABLE!>plus<!>(1)
x?.plus(1)
x <!NONE_APPLICABLE!>+<!> 1
<!INAPPLICABLE_CANDIDATE!>-<!>x
x.<!INAPPLICABLE_CANDIDATE!>unaryMinus<!>()
<!UNSAFE_CALL!>-<!>x
x.<!UNSAFE_CALL!>unaryMinus<!>()
x?.unaryMinus()
a.<!INAPPLICABLE_CANDIDATE!>plus<!>(1)
a.<!UNSAFE_CALL!>plus<!>(1)
a?.plus(1)
a <!INAPPLICABLE_CANDIDATE!>plus<!> 1
a <!INAPPLICABLE_CANDIDATE!>+<!> 1
<!INAPPLICABLE_CANDIDATE!>-<!>a
a.<!INAPPLICABLE_CANDIDATE!>unaryMinus<!>()
a <!UNSAFE_CALL!>plus<!> 1
a <!UNSAFE_CALL!>+<!> 1
<!UNSAFE_CALL!>-<!>a
a.<!UNSAFE_CALL!>unaryMinus<!>()
a?.unaryMinus()
a.<!INAPPLICABLE_CANDIDATE!>div<!>(1)
a <!INAPPLICABLE_CANDIDATE!>/<!> 1
a <!INAPPLICABLE_CANDIDATE!>div<!> 1
a.<!UNSAFE_CALL!>div<!>(1)
a <!UNSAFE_CALL!>/<!> 1
a <!UNSAFE_CALL!>div<!> 1
a?.div(1)
a.times(1)
@@ -34,8 +34,8 @@ fun test(x : Int?, a : A?) {
a times 1
a?.times(1)
1 <!INAPPLICABLE_CANDIDATE!>in<!> a
a <!INAPPLICABLE_CANDIDATE!>contains<!> 1
a.<!INAPPLICABLE_CANDIDATE!>contains<!>(1)
1 <!UNSAFE_CALL!>in<!> a
a <!UNSAFE_CALL!>contains<!> 1
a.<!UNSAFE_CALL!>contains<!>(1)
a?.contains(1)
}
@@ -7,7 +7,7 @@ fun main() {
val x: Foo? = null
val y: Foo? = null
x.<!INAPPLICABLE_CANDIDATE!>foo<!>(y)
x.<!UNSAFE_CALL!>foo<!>(y)
x!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(y)
x.foo(y!!)
x!!.foo(y!!)
@@ -16,8 +16,8 @@ fun main() {
val b: Foo? = null
val c: Foo? = null
a.<!INAPPLICABLE_CANDIDATE!>foo<!>(b.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a!!.foo(b.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a.<!UNSAFE_CALL!>foo<!>(b.<!UNSAFE_CALL!>foo<!>(c))
a!!.foo(b.<!UNSAFE_CALL!>foo<!>(c))
a.foo(b!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a!!.foo(b!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a.foo(b.foo(c!!))
@@ -6,8 +6,8 @@ fun A.bar() {}
fun A?.buzz() {}
fun test(a : A?) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() // error
a.<!INAPPLICABLE_CANDIDATE!>bar<!>() // error
a.<!UNSAFE_CALL!>foo<!>() // error
a.<!UNSAFE_CALL!>bar<!>() // error
a.buzz()
a?.foo()
@@ -30,12 +30,12 @@ fun A.test2() {
}
fun A?.test3() {
<!INAPPLICABLE_CANDIDATE!>foo<!>() // error
<!INAPPLICABLE_CANDIDATE!>bar<!>() // error
<!UNSAFE_CALL!>foo<!>() // error
<!UNSAFE_CALL!>bar<!>() // error
buzz()
this.<!INAPPLICABLE_CANDIDATE!>foo<!>() // error
this.<!INAPPLICABLE_CANDIDATE!>bar<!>() // error
this.<!UNSAFE_CALL!>foo<!>() // error
this.<!UNSAFE_CALL!>bar<!>() // error
this.buzz()
this?.foo()
@@ -5,7 +5,7 @@ package kt1270
fun foo() {
val sc = java.util.HashMap<String, SomeClass>()[""]
val value = sc.<!INAPPLICABLE_CANDIDATE!>value<!>
val value = sc.<!UNSAFE_CALL!>value<!>
}
private class SomeClass() {
@@ -5,7 +5,7 @@ package e
fun main() {
val compareTo = 1
val s: String? = null
s.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("")
s.<!UNSAFE_CALL!>compareTo<!>("")
val bar = 2
s.<!UNRESOLVED_REFERENCE!>bar<!>()
@@ -13,5 +13,5 @@ public class B {
// FILE: main.kt
fun test() {
B.bar() { it.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() > 0 }
B.bar() { it.<!UNSAFE_CALL!>hashCode<!>() > 0 }
}
@@ -22,11 +22,11 @@ fun test() {
var platformJ = J.staticJ
+platformNN
<!INAPPLICABLE_CANDIDATE!>+<!>platformN
<!UNSAFE_CALL!>+<!>platformN
+platformJ
++platformNN
<!INAPPLICABLE_CANDIDATE!>++<!>platformN
<!UNSAFE_CALL!>++<!>platformN
++platformJ
platformNN++
@@ -21,11 +21,11 @@ fun test() {
val platformJ = J.staticJ
platformNN[0]
<!INAPPLICABLE_CANDIDATE!>platformN[0]<!>
<!UNSAFE_CALL!>platformN[0]<!>
platformJ[0]
platformNN[0] = 1
<!INAPPLICABLE_CANDIDATE!>platformN[0] = 1<!>
<!UNSAFE_CALL!>platformN[0] = 1<!>
platformJ[0] = 1
}
@@ -43,6 +43,6 @@ fun test() {
platformJ || false
!platformNN
<!INAPPLICABLE_CANDIDATE!>!<!>platformN
<!UNSAFE_CALL!>!<!>platformN
!platformJ
}
@@ -19,5 +19,5 @@ public class J {
// FILE: k.kt
var A by J.staticNN
var B by <!INAPPLICABLE_CANDIDATE!>J.staticN<!>
var B by <!UNSAFE_CALL!>J.staticN<!>
var C by J.staticJ
@@ -23,14 +23,14 @@ fun test() {
val platformJ = J.staticJ
platformNN.foo()
platformN.<!INAPPLICABLE_CANDIDATE!>foo<!>()
platformN.<!UNSAFE_CALL!>foo<!>()
platformJ.foo()
with(platformNN) {
foo()
}
with(platformN) {
<!INAPPLICABLE_CANDIDATE!>foo<!>()
<!UNSAFE_CALL!>foo<!>()
}
with(platformJ) {
foo()
@@ -25,14 +25,14 @@ fun test() {
val platformJ = J.staticJ
platformNN.foo()
platformN.<!INAPPLICABLE_CANDIDATE!>foo<!>()
platformN.<!UNSAFE_CALL!>foo<!>()
platformJ.foo()
with(platformNN) {
foo()
}
with(platformN) {
<!INAPPLICABLE_CANDIDATE!>foo<!>()
<!UNSAFE_CALL!>foo<!>()
}
with(platformJ) {
foo()
@@ -22,7 +22,7 @@ fun test() {
val platformJ = J.staticJ
for (x in platformNN) {}
<!INAPPLICABLE_CANDIDATE!>for (x in platformN) {}<!>
<!UNSAFE_CALL!>for (x in platformN) {}<!>
for (x in platformJ) {}
}
@@ -18,6 +18,6 @@ public class J {
fun test() {
J.staticNN()
J.<!INAPPLICABLE_CANDIDATE!>staticN<!>()
J.<!UNSAFE_CALL!>staticN<!>()
J.staticJ()
}
@@ -16,7 +16,7 @@ public class J {
fun foo(collection: Collection<J>) {
val mapped = collection.map { it.method() }
mapped[0].<!INAPPLICABLE_CANDIDATE!>length<!>
mapped[0].<!UNSAFE_CALL!>length<!>
}
public fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
@@ -1,32 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FILE: J.java
import org.jetbrains.annotations.*;
public class J {
public interface Multi {
String component1();
String component2();
}
@NotNull
public static Multi staticNN;
@Nullable
public static Multi staticN;
public static Multi staticJ;
}
// FILE: k.kt
fun test() {
// @NotNull platform type
val platformNN = J.staticNN
// @Nullable platform type
val platformN = J.staticN
// platform type with no annotation
val platformJ = J.staticJ
val (a1, b1) = platformNN
val (<!INAPPLICABLE_CANDIDATE!>a2<!>, <!INAPPLICABLE_CANDIDATE!>b2<!>) = platformN
val (a3, b3) = platformJ
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FILE: J.java
@@ -21,11 +21,11 @@ fun test() {
val platformJ = J.staticJ
platformNN[0]
<!INAPPLICABLE_CANDIDATE!>platformN[0]<!>
<!UNSAFE_CALL!>platformN[0]<!>
platformJ[0]
platformNN[0] = 1
<!INAPPLICABLE_CANDIDATE!>platformN[0] = 1<!>
<!UNSAFE_CALL!>platformN[0] = 1<!>
platformJ[0] = 1
}
@@ -8,8 +8,8 @@ class E : B1() {
fun baz() {
val x: String? = ""
x.<!INAPPLICABLE_CANDIDATE!>foo<!>(x)
x.<!INAPPLICABLE_CANDIDATE!>foo<!>("")
x.<!UNSAFE_CALL!>foo<!>(x)
x.<!UNSAFE_CALL!>foo<!>("")
x.<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
x.bar("")
}
@@ -19,5 +19,5 @@ class C(p: Any, val v: Any) {
var test5
get() { return <!UNRESOLVED_REFERENCE!>p<!> }
set(nv) { <!UNRESOLVED_REFERENCE!>p<!>.<!INAPPLICABLE_CANDIDATE!>let<!> {} }
set(nv) { <!UNRESOLVED_REFERENCE!>p<!>.<!UNSAFE_CALL!>let<!> {} }
}
@@ -10,7 +10,7 @@ class C(override val t: Any?) : B<Any?, Any>
fun f(b: B<*, Any>) {
val y = b.t
if (y is String?) {
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
}
@@ -14,6 +14,6 @@ fun f(): Unit {
val i : Int? = null
i <!NONE_APPLICABLE!>+<!> 1
set + 1
1 <!INAPPLICABLE_CANDIDATE!>in<!> set
1 <!UNSAFE_CALL!>in<!> set
1 in 2
}
@@ -8,5 +8,5 @@ fun Array<String>.length() : Int {
}
fun test(array : Array<String?>?) {
array?.sure<Array<String?>>().<!INAPPLICABLE_CANDIDATE!>length<!>()
array?.sure<Array<String?>>().<!UNSAFE_CALL!>length<!>()
}
@@ -4,7 +4,7 @@
operator fun String.invoke(i: Int) {}
fun foo(s: String?) {
<!INAPPLICABLE_CANDIDATE!>s<!>(1)
<!UNSAFE_CALL!>s<!>(1)
<!INAPPLICABLE_CANDIDATE!>(s ?: null)(1)<!>
<!UNSAFE_CALL!>(s ?: null)(1)<!>
}
@@ -12,7 +12,7 @@ class Another1 {
fun Another1.main(x: Bar1<String>?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
x?.value.<!UNSAFE_CALL!>invoke<!>({})
}
// Test case 2: additional receiver, non-generic invoke
@@ -26,7 +26,7 @@ class Another2 {
fun Another2.main(x: Bar2<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
x?.value.<!UNSAFE_CALL!>invoke<!>(1)
}
// Test case 3: additional generic receiver, generic invoke
@@ -40,7 +40,7 @@ class Another3<T> {
fun <K> Another3<K>.main(x: Bar3<K>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
x?.value.<!UNSAFE_CALL!>invoke<!>(1)
}
// Test case 4: additional receiver, generic invoke with nullable receiver
@@ -68,7 +68,7 @@ class Another5 {
fun Another5.main(x: Bar5?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
x?.value.<!UNSAFE_CALL!>invoke<!>({})
}
// Test case 6: top-level generic invoke
@@ -96,7 +96,7 @@ operator fun <T> Foo7<T>.invoke(x: Int) {}
fun Another7.main(x: Bar7<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
x?.value.<!UNSAFE_CALL!>invoke<!>(1)
}
// Test case 8: top-level non-generic invoke
@@ -136,5 +136,5 @@ class Another10 {
fun Another10.main(x: Bar10<String>?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
x?.value.<!UNSAFE_CALL!>invoke<!>({})
}
@@ -7,8 +7,8 @@ fun test(a: A) {
(a.x)("")
}
"".<!UNRESOLVED_REFERENCE!>(a.x)()<!>
a.<!INAPPLICABLE_CANDIDATE!>x<!>("")
<!INAPPLICABLE_CANDIDATE!>(a.x)("")<!>
a.<!UNSAFE_CALL!>x<!>("")
<!UNSAFE_CALL!>(a.x)("")<!>
with("") {
a.<!INAPPLICABLE_CANDIDATE!>x<!>()
@@ -14,7 +14,7 @@ class MemberInvokeOwner {
class Cls {
fun testImplicitReceiver() {
<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
<!UNSAFE_CALL!>nullableExtensionProperty<!>()
}
}
@@ -30,7 +30,7 @@ fun testNullableReceiver(nullable: Cls?) {
}
fun testNotNullableReceiver(notNullable: Cls) {
notNullable.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
notNullable.<!UNSAFE_CALL!>nullableExtensionProperty<!>()
notNullable?.extensionProperty()
}
@@ -38,6 +38,6 @@ fun testFlexibleReceiver() {
val flexible = JavaClass.createFlexible()
flexible.extensionProperty()
flexible?.extensionProperty()
flexible.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
flexible?.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
flexible.<!UNSAFE_CALL!>nullableExtensionProperty<!>()
flexible?.<!UNSAFE_CALL!>nullableExtensionProperty<!>()
}
+2 -2
View File
@@ -1,7 +1,7 @@
// !WITH_NEW_INFERENCE
fun f(s: String, action: (String.() -> Unit)?) {
s.foo().bar().<!INAPPLICABLE_CANDIDATE!>action<!>()
s.foo().bar().<!UNSAFE_CALL!>action<!>()
}
fun String.foo() = ""
@@ -12,4 +12,4 @@ fun String.bar() = ""
val functions: Map<String, () -> Any> = TODO()
fun run(name: String) = <!INAPPLICABLE_CANDIDATE!>functions[name]()<!>
fun run(name: String) = <!UNSAFE_CALL!>functions[name]()<!>
@@ -22,9 +22,9 @@ public interface J {
// FILE: 1.kt
fun test(j: J) {
j.<!AMBIGUITY!>foo<!>({ <!UNRESOLVED_REFERENCE!>it<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" }, "") <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
j.<!AMBIGUITY!>foo<!>({ <!UNRESOLVED_REFERENCE!>it<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" }, "") <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
j.<!AMBIGUITY!>bas<!>({ <!UNRESOLVED_REFERENCE!>it<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" }, "") <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
j.<!AMBIGUITY!>bas<!>({ <!UNRESOLVED_REFERENCE!>it<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" }, "") <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
// NI: TODO
j.bar { it checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" } checkType { _<Int>() }
@@ -21,9 +21,9 @@ interface K {
}
fun test(k: K) {
k.<!AMBIGUITY!>foo<!> { <!UNRESOLVED_REFERENCE!>it<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" } <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
k.<!AMBIGUITY!>foo<!> { <!UNRESOLVED_REFERENCE!>it<!> <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" } <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
k.<!AMBIGUITY!>bas<!> { <!UNRESOLVED_REFERENCE!>it<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { _<Any?>() }; "" } <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
k.<!AMBIGUITY!>bas<!> { <!UNRESOLVED_REFERENCE!>it<!> <!UNSAFE_CALL!>checkType<!> { _<Any?>() }; "" } <!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
// NI: TODO
k.bar { it checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() }; "" } checkType { _<Int>() }
@@ -3,7 +3,7 @@ fun foo(): String {
var s: String?
s = null
s?.length
s.<!INAPPLICABLE_CANDIDATE!>length<!>
s.<!UNSAFE_CALL!>length<!>
if (s == null) return s!!
var t: String? = "y"
if (t == null) t = "x"
@@ -13,7 +13,7 @@ fun g(a: SomeClass?) {
// 'a' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(a as SomeSubClass).foo
}
val b = (a as? SomeSubClass)?.foo
@@ -21,7 +21,7 @@ fun g(a: SomeClass?) {
// 'a' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(a as SomeSubClass).foo
}
val c = a as? SomeSubClass
@@ -29,7 +29,7 @@ fun g(a: SomeClass?) {
// 'a' and 'c' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
c.hashCode()
c.foo
}
@@ -13,7 +13,7 @@ fun g(a: SomeClass?) {
// 'a' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(a as SomeSubClass).foo
}
val b = (a as? SomeSubClass)?.foo
@@ -21,7 +21,7 @@ fun g(a: SomeClass?) {
// 'a' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(a as SomeSubClass).foo
}
val c = a as? SomeSubClass
@@ -29,7 +29,7 @@ fun g(a: SomeClass?) {
// 'a' and 'c' can be cast to SomeSubClass
a.hashCode()
a.foo
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
c.hashCode()
c.foo
}
@@ -18,18 +18,18 @@ fun g(a: SomeClass?) {
b = "Hello"
if (b != null) {
// 'a' cannot be cast to SomeSubClass!
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
a.<!UNSAFE_CALL!>hashCode<!>()
a.<!UNRESOLVED_REFERENCE!>foo<!>
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(a as SomeSubClass).foo
}
var c = a as? SomeSubClass
c = Impl
if (c != null) {
// 'a' cannot be cast to SomeSubClass
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
a.<!UNSAFE_CALL!>hashCode<!>()
a.<!UNRESOLVED_REFERENCE!>foo<!>
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(a as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
c.hashCode()
c.foo
}
@@ -41,18 +41,18 @@ fun f(a: SomeClass?) {
if (aa as? SomeSubClass != null) {
aa = null
// 'aa' cannot be cast to SomeSubClass
aa.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
aa.<!UNSAFE_CALL!>hashCode<!>()
aa.<!UNRESOLVED_REFERENCE!>foo<!>
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(aa as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(aa as SomeSubClass).foo
}
val b = (aa as? SomeSubClass)?.foo
aa = null
if (b != null) {
// 'aa' cannot be cast to SomeSubClass
aa.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
aa.<!UNSAFE_CALL!>hashCode<!>()
aa.<!UNRESOLVED_REFERENCE!>foo<!>
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(aa as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
(aa as SomeSubClass).foo
}
aa = a
@@ -61,7 +61,7 @@ fun f(a: SomeClass?) {
// 'c' can be cast to SomeSubClass
aa.hashCode()
aa.foo
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
(aa as? SomeSubClass).<!UNSAFE_CALL!>foo<!>
c.hashCode()
c.foo
}
@@ -6,30 +6,30 @@ fun foo(x : String?, y : String?) {
y.length
}
else {
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
if (y != null || x == y) {
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
else {
// y == null but x != y
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
if (y == null && x != y) {
// y == null but x != y
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
else {
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
if (y == null || x != y) {
x.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!INAPPLICABLE_CANDIDATE!>length<!>
x.<!UNSAFE_CALL!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
else {
// Both not null
@@ -3,21 +3,21 @@ fun foo(x: String?, y: String?, z: String?, w: String?) {
if (x != null && y != null && (x == z || y == z))
z.length
else
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
if (x != null || y != null || (x != z && y != z))
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
else
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
if (x == null || y == null || (x != z && y != z))
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
else
z.length
if (x != null && y == x && z == y && w == z)
w.length
else
w.<!INAPPLICABLE_CANDIDATE!>length<!>
w.<!UNSAFE_CALL!>length<!>
if ((x != null && y == x) || (z != null && y == z))
y.length
else
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
@@ -1,26 +1,26 @@
fun foo(x: String?, y: String?, z: String?) {
if ((x!!.hashCode() == 0 || y!!.hashCode() == 1) && z!!.hashCode() == 2) {
x.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
// condition is true => z!! after and is called
z.length
}
else {
x.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
z.<!UNSAFE_CALL!>length<!>
}
// First element is always analyzed
x.length
var xx = y ?: z
if ((xx!!.hashCode() == 0 && y!!.hashCode() == 1) || z!!.hashCode() == 2) {
xx.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
z.<!UNSAFE_CALL!>length<!>
}
else {
xx.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
// condition is false => z!! after or is called
z.length
}
@@ -35,16 +35,16 @@ fun foo(x: String?, y: String?, z: String?) {
}
else {
xx.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
z.<!UNSAFE_CALL!>length<!>
}
// First element is always analyzed
x.length
xx = y ?: z
if (xx!!.hashCode() == 0 || y!!.hashCode() == 1 || z!!.hashCode() == 2) {
xx.length
y.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
z.<!UNSAFE_CALL!>length<!>
}
else {
// all three are called
@@ -11,13 +11,13 @@ interface Order {
fun foo(o: Any) {
val order = o as? Order
if (order?.expired ?: false) {
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
order.<!UNSAFE_CALL!>doSomething<!>()
}
else {
}
if (order?.notExpired() ?: false) {
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
order.<!UNSAFE_CALL!>doSomething<!>()
}
}
@@ -39,12 +39,12 @@ fun bar(o: Any) {
fun baz(o: Boolean?) {
if (o ?: false) {
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
o.<!UNSAFE_CALL!>hashCode<!>()
}
if (o ?: true) {
}
else {
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
o.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -11,13 +11,13 @@ interface Order {
fun foo(o: Any) {
val order = o as? Order
if (order?.expired ?: false) {
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
order.<!UNSAFE_CALL!>doSomething<!>()
}
else {
}
if (order?.notExpired() ?: false) {
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
order.<!UNSAFE_CALL!>doSomething<!>()
}
}
@@ -39,12 +39,12 @@ fun bar(o: Any) {
fun baz(o: Boolean?) {
if (o ?: false) {
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
o.<!UNSAFE_CALL!>hashCode<!>()
}
if (o ?: true) {
}
else {
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
o.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -1,7 +1,7 @@
// Based on KT-9100
fun test(x: Any?, y: Any?): Any {
val z = x ?: y!!
y.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
y.<!UNSAFE_CALL!>hashCode<!>()
// !! / ?. is necessary here, because y!! above may not be executed
y?.hashCode()
y!!.hashCode()
@@ -4,7 +4,7 @@ class C {
fun test(a: C?, nn: () -> Nothing?) {
a ?: nn()
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.<!UNSAFE_CALL!>foo<!>()
a ?: return
a.foo()
@@ -12,7 +12,7 @@ fun printMessages() {
Message.HELLO.text!!
Message.HELLO.text.length
Message.NOTHING.text.<!INAPPLICABLE_CANDIDATE!>length<!>
Message.NOTHING.text.<!UNSAFE_CALL!>length<!>
Message.NOTHING.text!!
Message.NOTHING.text.length
@@ -12,7 +12,7 @@ fun printMessages() {
Message.HELLO.text!!
Message.HELLO.text.length
Message.NOTHING.text.<!INAPPLICABLE_CANDIDATE!>length<!>
Message.NOTHING.text.<!UNSAFE_CALL!>length<!>
Message.NOTHING.text!!
Message.NOTHING.text.length
@@ -2,12 +2,12 @@ class D(val a: String, val b: Boolean)
fun foo(p: Boolean, v: D?): String {
if (p && v!!.b) v.a
else v.<!INAPPLICABLE_CANDIDATE!>a<!>
else v.<!UNSAFE_CALL!>a<!>
if (p && v!! == D("?", false)) v.a
else v.<!INAPPLICABLE_CANDIDATE!>a<!>
if (p || v!!.b) v.<!INAPPLICABLE_CANDIDATE!>a<!>
else v.<!UNSAFE_CALL!>a<!>
if (p || v!!.b) v.<!UNSAFE_CALL!>a<!>
else v.a
if (p || v!! == D("?", false)) v.<!INAPPLICABLE_CANDIDATE!>a<!>
if (p || v!! == D("?", false)) v.<!UNSAFE_CALL!>a<!>
else v.a
return ""
}
@@ -9,5 +9,5 @@ fun <T> T?.let(f: (T) -> Unit) {
fun test(your: Your?) {
(your?.foo() as? Any)?.let {}
// strange smart cast to 'Your' at this point
your.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
your.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -7,6 +7,6 @@ fun foo() {
var y: My? = My(42)
if (y!!.x != null) {
y = My(null)
y!!.x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
y!!.x.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -9,6 +9,6 @@ fun foo() {
var y: My? = My(42)
if (y!!.x != null) {
y = My(null)
(y + My(0)).x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
(y + My(0)).x.<!UNSAFE_CALL!>hashCode<!>()
}
}
@@ -5,7 +5,7 @@ class A<E> {
class B(var a: A<*>?) {
fun bar() {
if (a != null) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
a.<!UNSAFE_CALL!>foo<!>()
}
}
}
@@ -33,6 +33,6 @@ fun test() {
x.baz(1).checkType { _<Unit>() }
x.<!INAPPLICABLE_CANDIDATE!>baz<!>(1, 2)
x.<!UNRESOLVED_REFERENCE!>foobar<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
x.<!UNRESOLVED_REFERENCE!>foobar<!>().<!UNSAFE_CALL!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
}
}
@@ -14,7 +14,7 @@ inline fun <R> callItContracted(fn: () -> R): R {
fun smartIt(p1: String?, p2: String?) {
p1 ?: callIt { return }
p1.<!INAPPLICABLE_CANDIDATE!>length<!>
p1.<!UNSAFE_CALL!>length<!>
p2 ?: callItContracted { return }
p2.length
@@ -6,5 +6,5 @@ fun <R> callIt(fn: () -> R): R = TODO()
fun smartIt(p1: String?, p2: String?) {
p1 ?: callIt { TODO() }
p1.<!INAPPLICABLE_CANDIDATE!>length<!> // smartcast
p1.<!UNSAFE_CALL!>length<!> // smartcast
}
@@ -36,7 +36,7 @@ fun kt6840_2(s: String?) {
fun kt1635(s: String?) {
s?.hashCode()!!
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
s.<!UNSAFE_CALL!>hashCode<!>()
}
fun kt2127() {
@@ -9,5 +9,5 @@ fun checkJump(x: Int?, y: Int?) {
y.hashCode()
}
// Smart cast here is erroneous: y is nullable
y.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
y.<!UNSAFE_CALL!>hashCode<!>()
}
@@ -4,8 +4,8 @@ public fun foo(x: String?, y: String?): Int {
// z is not null in both branches
z.length
// y is nullable if x != null
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
// y is null because of the break
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
return y.<!UNSAFE_CALL!>length<!>
}
@@ -13,5 +13,5 @@ public fun foo(x: String?): Int {
checkSubtype<Int>(y)
}
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -10,7 +10,7 @@ public fun foo(x: String?, z: String?, w: String?): Int {
// w is not null because of w!!
w.length
// z is nullable despite of z!!
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -7,7 +7,7 @@ public fun foo(x: String?, z: String?): Int {
gav(if (x == null) break else x, z!!)
} while (bar())
// z is nullable despite of z!!
z.<!INAPPLICABLE_CANDIDATE!>length<!>
z.<!UNSAFE_CALL!>length<!>
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -10,5 +10,5 @@ public fun foo(x: String?): Int {
} while (bar())
y.hashCode()
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -9,5 +9,5 @@ public fun foo(x: String?, z: String?): Int {
// z is not null because of z!!
z.length
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -12,5 +12,5 @@ public fun foo(x: String?, z: String?, w: String?): Int {
// z is not null because of z!!
z.length
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -9,5 +9,5 @@ public fun foo(p: String?): Int {
p!!.length
} while (!x())
// Here we have do while loop but p is still nullable due to break before
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
return p.<!UNSAFE_CALL!>length<!>
}
@@ -5,5 +5,5 @@ fun foo(s: String?): Int {
if (bar()) break
} while (s!!.length > 0)
// This call is unsafe due to break
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
return s.<!UNSAFE_CALL!>length<!>
}
@@ -6,5 +6,5 @@ public fun foo(p: String?): Int {
if (p != null) break
} while (!x())
// p can be null despite of the break
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
return p.<!UNSAFE_CALL!>length<!>
}
@@ -5,5 +5,5 @@ fun foo(s: String?): Int {
if (bar()) break
} while (s==null)
// This call is unsafe due to break
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
return s.<!UNSAFE_CALL!>length<!>
}
@@ -6,5 +6,5 @@ public fun foo(x: String?): Int {
x.length
} while (true)
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -2,8 +2,8 @@ public fun foo(x: String?, y: String?): Int {
while (true) {
x ?: if (y == null) break
// y is nullable if x != null
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
// y is null because of the break
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
return y.<!UNSAFE_CALL!>length<!>
}
@@ -2,8 +2,8 @@ public fun foo(x: String?, y: String?): Int {
while (true) {
(if (x != null) break else y) ?: y!!
// y is not null in both branches but it's hard to determine
y.<!INAPPLICABLE_CANDIDATE!>length<!>
y.<!UNSAFE_CALL!>length<!>
}
// y can be null because of the break
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
return y.<!UNSAFE_CALL!>length<!>
}
@@ -10,5 +10,5 @@ public fun foo(x: String?): Int {
} while (bar())
y.hashCode()
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -6,5 +6,5 @@ public fun foo(x: String?): Int {
// In future we can infer this initialization
<!UNINITIALIZED_VARIABLE!>y<!>.hashCode()
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -6,5 +6,5 @@ public fun foo(x: String?): Int {
y.length
}
// x is null because of the break
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
return x.<!UNSAFE_CALL!>length<!>
}
@@ -7,5 +7,5 @@ public fun foo(x: String?, y: String?): Int {
y.length
}
// y is null because of the break
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
return y.<!UNSAFE_CALL!>length<!>
}

Some files were not shown because too many files have changed in this diff Show More