[FIR] Harden check of argument type properly

Before this commit, nullable argument could match not null parameter.
Now we require also correct nullability that breaks some cases
This commit is contained in:
simon.ogorodnik
2020-01-28 14:17:24 +03:00
committed by Mikhail Glukhikh
parent fe779bf7bd
commit 34e6649d31
82 changed files with 171 additions and 173 deletions
@@ -254,9 +254,7 @@ private fun checkApplicabilityForArgumentType(
}
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
if (!isReceiver) {
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) {
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
}
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
return
}
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) {
@@ -27,5 +27,5 @@ FILE: factoryFunctionOverloads.kt
public final fun foo(c: R|C|, b: R|B|, bn: R|B?|): R|kotlin/Unit| {
lval x: R|A| = R|/A|(R|<local>/c|)
lval y: R|A| = R|/A.A|(R|<local>/b|)
lval z: R|A| = R|/A.A|(R|<local>/bn|)
lval z: R|A| = R|/A|(R|<local>/bn|)
}
@@ -2,6 +2,6 @@ fun bar(doIt: Int.() -> Int) {
1.doIt()
1?.doIt()
val i: Int? = 1
i.doIt()
i.<!INAPPLICABLE_CANDIDATE!>doIt<!>()
i?.doIt()
}
@@ -23,8 +23,8 @@ fun <T> test(x: T) {
baz<Int?, String?>(null, null, ::foo)
baz<Int, String?>(null, null, ::foo)
baz<Int?, String>(null, null, ::foo)
<!INAPPLICABLE_CANDIDATE!>baz<!><Int, String?>(null, null, ::foo)
<!INAPPLICABLE_CANDIDATE!>baz<!><Int?, String>(null, null, ::foo)
baz(null, "", ::foo)
baz(1, null, ::foo)
baz(null, null, ::foo)
@@ -5,9 +5,9 @@ fun foo() {
val x: Int? = null
if (x != null && bar(x) == 0) bar(bar(x))
bar(x)
if (x == null || bar(x) == 0) bar(bar(x))
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x == null || bar(x) == 0) bar(<!INAPPLICABLE_CANDIDATE!>bar<!>(x))
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x is Int && bar(x)*bar(x) == bar(x)) bar(x)
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
}
@@ -4,10 +4,10 @@ fun foo() {
val x: Int? = null
val a = Array<Int>(3, {0})
if (x != null) bar(a[x]) else bar(a[x])
if (x != null) bar(a[x]) else bar(<!INAPPLICABLE_CANDIDATE!>a[x]<!>)
bar(a[if (x == null) 0 else x])
bar(a[x])
bar(<!INAPPLICABLE_CANDIDATE!>a[x]<!>)
"123"[x];
<!INAPPLICABLE_CANDIDATE!>"123"[x]<!>;
if (x != null) "123"[x];
}
@@ -6,6 +6,6 @@ fun foo() {
val x: Int? = null
bar(1 + (if (x == null) 0 else x))
bar(if (x == null) x else x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (x == null) x else x)
if (x != null) bar(x + x/(x-x*x))
}
@@ -17,14 +17,14 @@ fun foo() {
if (x == null) bar(x) else bar(x)
bar(bar(x))
} else if (x == null) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x != null) {
bar(x)
if (x == null) bar(x)
if (x == null) bar(x) else bar(x)
bar(bar(x) + bar(x))
} else if (x == null) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
}
}
@@ -4,13 +4,13 @@ fun foo() {
val x: Int? = null
do {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
} while (x == null)
bar(x)
val y: Int? = null
do {
bar(y)
<!INAPPLICABLE_CANDIDATE!>bar<!>(y)
} while (y != null)
bar(y)
<!INAPPLICABLE_CANDIDATE!>bar<!>(y)
}
@@ -16,5 +16,5 @@ fun doWhileWithBreak(x: Int?, y0: Int) {
y++
if (y > 0) break
} while (x!! == y)
checkSubtype<Int>(x)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(x)
}
@@ -5,5 +5,5 @@ fun foo() {
bar(x ?: 0)
if (x != null) bar(x ?: x)
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
}
@@ -1,7 +1,7 @@
fun bar(x: Int) = x + 1
fun f1(x: Int?) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x != null) bar(x!!)
if (x == null) bar(x!!)
}
@@ -5,7 +5,7 @@ fun foo() {
val a = Array<Int>(3, {0})
for (p in a) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x == null) continue
bar(x)
for (q in a) {
@@ -15,7 +15,7 @@ fun foo() {
}
for (p in a) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x == null) break
bar(x)
}
@@ -3,7 +3,7 @@ fun bar(x: Int) = x + 1
fun foo() {
val x: Int? = null
fun baz() = bar(x)
fun baz() = <!INAPPLICABLE_CANDIDATE!>bar<!>(x)
fun quux() = if (x != null) bar(x) else baz()
fun quuux() = bar(if (x == null) 0 else x)
}
@@ -25,7 +25,7 @@ fun ifThenElse(x: Int?) {
fun ifIs(x: Int?, cond: Boolean) {
if ((x is Int) == cond) {
checkSubtype<Int>(x)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(x)
}
checkSubtype<Int>(x)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(x)
}
@@ -6,7 +6,7 @@ fun foo() {
bar(if (x == null) 0 else x)
if (x == null) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
return
} else {
bar(x)
@@ -17,14 +17,14 @@ fun foo() {
if (y is Int) {
bar(y)
} else {
bar(y)
<!INAPPLICABLE_CANDIDATE!>bar<!>(y)
return
}
bar(y)
val z: Int? = null
if (z != null) bar(z)
bar(z)
<!INAPPLICABLE_CANDIDATE!>bar<!>(z)
bar(z!!)
if (z != null) bar(z!!)
}
@@ -3,7 +3,7 @@ fun bar(x: Int): Int = x + 1
fun foo() {
val x: Int? = null
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x != 2) {
if (x == null) return
2<!AMBIGUITY!>+<!><!SYNTAX!><!>
@@ -7,7 +7,7 @@ class A {
fun foo() {
val x: Int? = null
A().bar(x)
A().<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x == null) return
A().bar(x)
}
@@ -5,7 +5,7 @@ fun bar(x: Int): Int = x + 1
fun foo(): Int {
val x: Int? = null
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x != null) return x
val y: Int? = null
@@ -8,14 +8,14 @@ class Derived : Base() {
fun foo() {
val x: Int? = null
super.bar(x)
this.baz(x)
super.<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
this.<!INAPPLICABLE_CANDIDATE!>baz<!>(x)
if (x == null) return
super.bar(x)
this.baz(x)
val y: Int? = null
if (y != null) super.bar(this.baz(y))
else this.baz(super.bar(y))
else this.baz(super.<!INAPPLICABLE_CANDIDATE!>bar<!>(y))
}
}
@@ -3,7 +3,7 @@ fun bar(x: Int): RuntimeException = RuntimeException(x.toString())
fun foo() {
val x: Int? = null
if (x == null) throw bar(x)
if (x == null) throw <!INAPPLICABLE_CANDIDATE!>bar<!>(x)
throw bar(x)
throw bar(x)
}
@@ -3,7 +3,7 @@ fun bar(x: Int): Int = x + 1
fun foo() {
val x: Int? = null
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
if (x == null) return
try {
bar(x)
@@ -3,7 +3,7 @@ fun bar(x: Int): Int = x + 1
fun foo() {
val x: Int? = null
while (x == null) {
bar(x)
<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
}
bar(x)
@@ -15,8 +15,8 @@ fun foo() {
val z: Int? = null
while (z == null) {
bar(z)
<!INAPPLICABLE_CANDIDATE!>bar<!>(z)
break
}
bar(z)
<!INAPPLICABLE_CANDIDATE!>bar<!>(z)
}
@@ -3,7 +3,7 @@
package kt1875
fun foo(a : Int?, b : Int.(Int)->Int) = a?.b(1) //unnecessary safe call warning
fun foo(a : Int?, b : Int.(Int)->Int) = a?.<!INAPPLICABLE_CANDIDATE!>b<!>(1) //unnecessary safe call warning
interface T {
val f : ((i: Int) -> Unit)?
@@ -7,10 +7,10 @@ fun <E : CharSequence> foo1(x: E) {}
fun <E : CharSequence> E.foo2() {}
fun <F : String?> bar(x: F) {
A(x)
<!INAPPLICABLE_CANDIDATE!>A<!>(x)
<!INAPPLICABLE_CANDIDATE!>A<!><F>(x)
foo1(x)
<!INAPPLICABLE_CANDIDATE!>foo1<!>(x)
<!INAPPLICABLE_CANDIDATE!>foo1<!><F>(x)
x.<!INAPPLICABLE_CANDIDATE!>foo2<!>()
@@ -5,7 +5,7 @@ fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
}
if (y != null) {
y(x)
<!INAPPLICABLE_CANDIDATE!>y<!>(x)
}
if (x != null && y != null) {
@@ -6,7 +6,7 @@ fun <T> foo(): T {
val x1: T = null
val x2: T? = null
bar<T>(null)
<!INAPPLICABLE_CANDIDATE!>bar<!><T>(null)
bar<T?>(null)
return null
@@ -23,7 +23,7 @@ class A<F> {
val x1: F = null
val x2: F? = null
xyz(null)
<!INAPPLICABLE_CANDIDATE!>xyz<!>(null)
bar<F?>(null)
return null
@@ -18,14 +18,14 @@ class A<F> {
x2.checkType { _<F>() }
<!INAPPLICABLE_CANDIDATE!>foo1<!><F?>(y)
foo1(y)
<!INAPPLICABLE_CANDIDATE!>foo1<!>(y)
foo2<F?>(y)
val x3 = foo2(y)
x3.checkType { _<F?>() }
foo1<F>(y)
foo2<F>(y)
<!INAPPLICABLE_CANDIDATE!>foo1<!><F>(y)
<!INAPPLICABLE_CANDIDATE!>foo2<!><F>(y)
foo1<Z>(z)
@@ -38,7 +38,7 @@ class A<F> {
x4.checkType { _<Z>() }
<!INAPPLICABLE_CANDIDATE!>foo1<!><W>(w)
foo1(w)
<!INAPPLICABLE_CANDIDATE!>foo1<!>(w)
foo2<W>(w)
val x6 = foo2(w)
@@ -13,6 +13,6 @@ fun <T : String?> foo(x: T) {
bar1(x)
bar2(x)
bar3(x)
bar4(x)
<!INAPPLICABLE_CANDIDATE!>bar3<!>(x)
<!INAPPLICABLE_CANDIDATE!>bar4<!>(x)
}
@@ -12,5 +12,5 @@ fun acceptA(a: A) {
fun main(i: I<*>) {
i.foo() checkType { <!UNRESOLVED_REFERENCE!>_<!><A?>() }
acceptA(i.foo()) // i.foo() should be nullable but isn't
<!INAPPLICABLE_CANDIDATE!>acceptA<!>(i.foo()) // i.foo() should be nullable but isn't
}
@@ -7,7 +7,7 @@ interface A<T>
fun <T> infer(a: A<T>) : T {}
fun test(nothing: Nothing?) {
val i = infer(nothing)
val i = <!INAPPLICABLE_CANDIDATE!>infer<!>(nothing)
}
fun sum(a : IntArray) : Int {
@@ -6,7 +6,7 @@ package kt1293
fun main() {
val intArray = arrayOfNulls<Int>(10)
val i : Int = intArray[0]
requiresInt(intArray[0])
<!INAPPLICABLE_CANDIDATE!>requiresInt<!>(intArray[0])
}
fun requiresInt(i: Int) {}
@@ -10,6 +10,6 @@ fun foo(s: String) {}
fun r(): Int? = null
fun test() {
foo(F().p())
<!INAPPLICABLE_CANDIDATE!>foo<!>(F().p())
<!INAPPLICABLE_CANDIDATE!>foo<!>(r())
}
@@ -8,7 +8,7 @@ fun <T> bar(a: T, b: Map<T, String>) = b.get(a)
fun test(a: Int) {
foo(a, null)
bar(a, null)
<!INAPPLICABLE_CANDIDATE!>bar<!>(a, null)
}
fun test1(a: Int) {
foo(a, throw Exception())
@@ -19,5 +19,5 @@ public class Y extends X<String> {
fun main() {
checkSubtype<Any>(Y().fooN())
Y().barN(null);
Y().<!INAPPLICABLE_CANDIDATE!>barN<!>(null);
}
@@ -19,5 +19,5 @@ public class Y extends X<A> {
fun main() {
checkSubtype<Any>(Y().fooN())
Y().barN(null);
Y().<!INAPPLICABLE_CANDIDATE!>barN<!>(null);
}
@@ -109,5 +109,5 @@ fun foo(x: SpecializedMap) {
x.remove(null)
x.<!AMBIGUITY!>put<!>(4, 5.0)
x.<!AMBIGUITY!>put<!>(4, null)
x.put(4, null)
}
@@ -20,5 +20,5 @@ class In<in F> {
fun test() {
A.foo().x() checkType { <!UNRESOLVED_REFERENCE!>_<!><Any?>() }
A.bar().y(null)
A.bar().<!INAPPLICABLE_CANDIDATE!>y<!>(null)
}
@@ -8,7 +8,7 @@ fun main() {
val y: Foo? = null
x.<!INAPPLICABLE_CANDIDATE!>foo<!>(y)
x!!.foo(y)
x!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(y)
x.foo(y!!)
x!!.foo(y!!)
@@ -18,8 +18,8 @@ fun main() {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>(b.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a!!.foo(b.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a.foo(b!!.foo(c))
a!!.foo(b!!.foo(c))
a.foo(b!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a!!.foo(b!!.<!INAPPLICABLE_CANDIDATE!>foo<!>(c))
a.foo(b.foo(c!!))
a!!.foo(b.foo(c!!))
a.foo(b!!.foo(c!!))
@@ -7,7 +7,7 @@ fun foo(x: Int): Int = x + 1
fun main() {
val x: Int? = null
foo(x)
<!INAPPLICABLE_CANDIDATE!>foo<!>(x)
if (x != null) {
foo(x)
@@ -15,14 +15,14 @@ fun main() {
foo(x)
}
foo(x)
<!INAPPLICABLE_CANDIDATE!>foo<!>(x)
if (x != null) {
foo(x)
foo(x!!)
foo(x)
} else {
foo(x)
<!INAPPLICABLE_CANDIDATE!>foo<!>(x)
foo(x!!)
foo(x)
}
@@ -15,8 +15,8 @@ fun foo() {
val y: Int? = 0
val z: Int? = 0
bar(if (y != null) y else z, y)
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (y != null) y else z, y)
y <!INAPPLICABLE_CANDIDATE!>+<!> 2
baz(y, y, if (y == null) return else y, y)
<!INAPPLICABLE_CANDIDATE!>baz<!>(y, y, if (y == null) return else y, y)
baz(y, z!!, z, y)
}
@@ -1,3 +1,3 @@
fun test(x: Int?) {
x in 1..2
x <!INAPPLICABLE_CANDIDATE!>in<!> 1..2
}
@@ -13,6 +13,6 @@ public class J {
fun test(j: J, nullStr: String?, nullByte: Byte?, nullDouble: Double?) {
j.foo(nullStr)
j.foo(nullDouble)
j.<!INAPPLICABLE_CANDIDATE!>foo<!>(nullDouble)
j.foo(nullByte)
}
@@ -6,8 +6,8 @@ fun foo(x: Int) {}
fun foo(x: Int, y: String) {}
fun bar(nullX: Int?, nullY: String?, notNullY: String) {
foo(nullX)
foo(nullX, notNullY)
foo(nullX, nullY)
<!INAPPLICABLE_CANDIDATE!>foo<!>(nullX)
<!INAPPLICABLE_CANDIDATE!>foo<!>(nullX, notNullY)
<!INAPPLICABLE_CANDIDATE!>foo<!>(nullX, nullY)
<!INAPPLICABLE_CANDIDATE!>foo<!>()
}
@@ -8,5 +8,5 @@ fun foo(i: Int) = i
fun test(a: A?) {
a?.b(1) //should be no warning
foo(a?.b(1)) //no warning, only error
<!INAPPLICABLE_CANDIDATE!>foo<!>(a?.b(1)) //no warning, only error
}
@@ -27,9 +27,9 @@ fun test(i: Int, ni: Int?) {
checkSubtype<C>(foo(2))
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.A>(J.<!AMBIGUITY!>foo<!>(2))
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.A>(J.<!AMBIGUITY!>foo<!>(i))
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.B>(J.<!AMBIGUITY!>foo<!>(ni))
checkSubtype<J.B>(J.foo(ni))
checkSubtype<C>(foo(ni))
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J.B>(J.<!AMBIGUITY!>foo<!>(ni))
checkSubtype<J.B>(J.foo(ni))
foo(J.getInteger())
J.<!AMBIGUITY!>foo<!>(J.getInteger())
@@ -12,5 +12,5 @@ import p.*
fun test() {
J()._int(1)
J()._int(null)
J().<!INAPPLICABLE_CANDIDATE!>_int<!>(null)
}
@@ -13,7 +13,7 @@ public class A {
fun test() {
A.bar(null, "")
A.bar<String>(null, "")
A.<!INAPPLICABLE_CANDIDATE!>bar<!><String>(null, "")
A.bar<String?>(null, "")
A.bar(null, A.platformString())
}
@@ -17,10 +17,10 @@ public class A<T> {
// FILE: k.kt
fun test() {
A.create().bar(null)
A.create().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
A.create().bar("")
A<String>().bar(null)
A<String?>().bar(null)
A<String>().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
A<String?>().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
A<String?>().bar("")
}
@@ -33,9 +33,9 @@ class C2 : A<String?>() {
}
fun test() {
B1().bar(null)
B2().bar(null)
B1().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
B2().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
C1().bar(null)
C1().<!INAPPLICABLE_CANDIDATE!>bar<!>(null)
}
@@ -34,7 +34,7 @@ fun test() {
platformJ++
1 + platformNN
1 + platformN
1 <!INAPPLICABLE_CANDIDATE!>+<!> platformN
1 + platformJ
platformNN + 1
@@ -42,7 +42,7 @@ fun test() {
platformJ + 1
1 plus platformNN
1 plus platformN
1 <!INAPPLICABLE_CANDIDATE!>plus<!> platformN
1 plus platformJ
platformNN plus 1
@@ -15,7 +15,7 @@ public class J {
fun test() {
val n = J.staticN
foo(n)
<!INAPPLICABLE_CANDIDATE!>foo<!>(n)
J.staticNN = n
if (n != null) {
foo(n)
@@ -23,7 +23,7 @@ fun test() {
val platformJ = J.staticJ
checkSubtype<J>(platformNN)
checkSubtype<J>(platformN)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><J>(platformN)
checkSubtype<J>(platformJ)
checkSubtype<J?>(platformNN)
@@ -15,7 +15,7 @@ public class J {
fun test() {
foo(J.staticNN)
foo(J.staticN)
<!INAPPLICABLE_CANDIDATE!>foo<!>(J.staticN)
foo(J.staticJ)
bar(J.staticNN)
@@ -54,8 +54,8 @@ fun test(n: J?, nn: J) {
J.staticSet(nn, nn, nn)
J.staticSet(platformNN, platformNN, platformNN)
J.staticSet(n, n, n)
J.staticSet(platformN, platformN, platformN)
J.<!INAPPLICABLE_CANDIDATE!>staticSet<!>(n, n, n)
J.<!INAPPLICABLE_CANDIDATE!>staticSet<!>(platformN, platformN, platformN)
J.staticSet(platformJ, platformJ, platformJ)
J().nn = n
@@ -78,13 +78,13 @@ fun test(n: J?, nn: J) {
J().set(nn, nn, nn)
J().set(platformNN, platformNN, platformNN)
J().set(n, n, n)
J().set(platformN, platformN, platformN)
J().<!INAPPLICABLE_CANDIDATE!>set<!>(n, n, n)
J().<!INAPPLICABLE_CANDIDATE!>set<!>(platformN, platformN, platformN)
J().set(platformJ, platformJ, platformJ)
J(nn, nn, nn)
J(platformNN, platformNN, platformNN)
J(n, n, n)
J(platformN, platformN, platformN)
<!INAPPLICABLE_CANDIDATE!>J<!>(n, n, n)
<!INAPPLICABLE_CANDIDATE!>J<!>(platformN, platformN, platformN)
J(platformJ, platformJ, platformJ)
}
@@ -10,7 +10,7 @@ class E : B1() {
x.<!INAPPLICABLE_CANDIDATE!>foo<!>(x)
x.<!INAPPLICABLE_CANDIDATE!>foo<!>("")
x.bar(x)
x.<!INAPPLICABLE_CANDIDATE!>bar<!>(x)
x.bar("")
}
@@ -19,7 +19,7 @@ class C {
fun p() : Resource? = null
fun bar() {
foo(p()) {
<!INAPPLICABLE_CANDIDATE!>foo<!>(p()) {
}
}
@@ -5,5 +5,5 @@
fun foo(i: Int) {}
fun test(s: String?) {
foo(s?.length)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s?.length)
}
@@ -4,19 +4,19 @@ package b
fun bar(i: Int) = i
fun test(a: Int?, b: Int?) {
bar(if (a == null) return else b)
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (a == null) return else b)
}
fun test(a: Int?, b: Int?, c: Int?) {
bar(if (a == null) return else if (b == null) return else c)
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (a == null) return else if (b == null) return else c)
}
fun test(a: Any?, b: Any?, c: Int?) {
bar(if (a == null) if (b == null) c else return else return)
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (a == null) if (b == null) c else return else return)
}
fun test(a: Int?, b: Any?, c: Int?) {
bar(if (a == null) {
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (a == null) {
return
} else {
if (b == null) {
@@ -15,7 +15,7 @@ class B {
fun test() {
if (A.x != null) {
useInt(A.x)
useInt(B.x)
<!INAPPLICABLE_CANDIDATE!>useInt<!>(B.x)
}
}
@@ -19,7 +19,7 @@ fun bar(x: String) = x
fun test(x: String?): Any {
val y = My.create()
val z = x ?: y!!
bar(y)
<!INAPPLICABLE_CANDIDATE!>bar<!>(y)
// !! / ?. is necessary here, because y!! above may not be executed
y?.hashCode()
y!!.hashCode()
@@ -6,10 +6,10 @@ class Test {
fun bar(a: Test, b: Test) {
if (a.foo != null) {
useInt(b.foo)
<!INAPPLICABLE_CANDIDATE!>useInt<!>(b.foo)
}
if (a.foo != null) {
useInt(foo)
<!INAPPLICABLE_CANDIDATE!>useInt<!>(foo)
}
if (this.foo != null) {
useInt(foo)
@@ -7,6 +7,6 @@ fun foo(a: MutableMap<String, String>, x: String?) {
}
fun foo1(a: MutableMap<String, String>, x: String?) {
a[x] = x!!
<!INAPPLICABLE_CANDIDATE!>a[x] = x!!<!>
a[x!!] = x
}
@@ -11,14 +11,14 @@ val i: Int? = 1
class A(val i: Int?) {
fun testUseFromClass() {
if (foo.i != null) {
useInt(i)
<!INAPPLICABLE_CANDIDATE!>useInt<!>(i)
}
}
}
fun testUseFromOtherPackage() {
if (bar.i != null) {
useInt(i)
<!INAPPLICABLE_CANDIDATE!>useInt<!>(i)
}
}
@@ -3,4 +3,4 @@ fun Any?.foo(my: My) = my === this
class My(val x: Any)
// my is nullable in brackets because Any?.foo has nullable receiver
fun foo(my: My?) = my?.x.foo(my)
fun foo(my: My?) = my?.x.<!INAPPLICABLE_CANDIDATE!>foo<!>(my)
@@ -7,5 +7,5 @@ fun bar(s: String): Int {
fun foo(m: MyClass): Int {
m.p = "xyz"
return bar(m.p)
return <!INAPPLICABLE_CANDIDATE!>bar<!>(m.p)
}
@@ -23,7 +23,7 @@ fun foo(k: KotlinClass) {
k.setSomething4("")
k.<!VARIABLE_EXPECTED!>something4<!> += ""
k.setSomething4(null)
k.<!INAPPLICABLE_CANDIDATE!>setSomething4<!>(null)
k.something4 = null
useString(k.getSomething5())
@@ -1,8 +1,8 @@
// !WITH_NEW_INFERENCE
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
javaInterface.doIt(null) { }
javaInterface.doIt("", null)
javaInterface.<!INAPPLICABLE_CANDIDATE!>doIt<!>(null) { }
javaInterface.<!INAPPLICABLE_CANDIDATE!>doIt<!>("", null)
}
// FILE: JavaInterface.java
@@ -32,7 +32,7 @@ abstract class MyIt7 : Iterator<String> {
fun foo(x: Iterator<String>, y: Iterator<String?>) {
x.forEachRemaining(null)
x.<!INAPPLICABLE_CANDIDATE!>forEachRemaining<!>(null)
x.forEachRemaining { it -> it.length }
x.forEachRemaining { it -> it?.length }
@@ -19,7 +19,7 @@ class KotlinMap2 : java.util.AbstractMap<String, Int>() {
fun foo(x: MutableMap<String, Int>, y: java.util.HashMap<String, Int>, z: java.util.AbstractMap<String, Int>) {
x.remove("", 1)
x.<!INAPPLICABLE_CANDIDATE!>remove<!>("", "")
x.remove("", null)
x.<!INAPPLICABLE_CANDIDATE!>remove<!>("", null)
y.remove("", 1)
y.remove("", "")
@@ -21,7 +21,7 @@ class Pair<X, Y>(val x: X, val y: Y)
typealias PL<T> = Pair<T, List<T>>
typealias PN<T> = Pair<T, Num<T>>
val test5 = PL(1, null)
val test5 = <!INAPPLICABLE_CANDIDATE!>PL<!>(1, null)
class Foo<T>(val p: Pair<T, T>)
@@ -31,7 +31,7 @@ fun getArr(): Array<String>? = null
fun f() {
A().foo(1, *args)
bar(2, *args)
<!INAPPLICABLE_CANDIDATE!>bar<!>(2, *args)
<!INAPPLICABLE_CANDIDATE!>baz<!>(*args)
}
@@ -55,7 +55,7 @@ fun h(b: B) {
fun k() {
A().foo(1, *getArr())
bar(2, *getArr())
<!INAPPLICABLE_CANDIDATE!>bar<!>(2, *getArr())
<!INAPPLICABLE_CANDIDATE!>baz<!>(*getArr())
}
@@ -46,7 +46,7 @@ fun main() {
a.bar()
a.baz(listOf())
a.<!AMBIGUITY!>manyParams<!>(null)
a.manyParams(null)
a.manyParams(any<kotlin.jvm.functions.FunctionN<Unit>>())
// Potentially, this would have better to forbid calling manyParams, too.
@@ -6,12 +6,12 @@ fun bar(): String? = null
fun foo() {
var x = ArrayList<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
x[0] = null
x[0] = bar()
<!INAPPLICABLE_CANDIDATE!>x[0] = null<!>
<!INAPPLICABLE_CANDIDATE!>x[0] = bar()<!>
x[0] = ""
val b1: MutableList<String?> = x
@@ -24,8 +24,8 @@ fun bar(): String? = null
fun foo() {
var x = A<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
val b1: Collection<String?> = x
@@ -24,12 +24,12 @@ fun bar(): String? = null
fun foo() {
var x = A<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
x[0] = null
x[0] = bar()
<!INAPPLICABLE_CANDIDATE!>x[0] = null<!>
<!INAPPLICABLE_CANDIDATE!>x[0] = bar()<!>
x[0] = ""
val b1: MutableList<String?> = x
@@ -10,14 +10,14 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String, Int> = HashMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>("", null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
<!INAPPLICABLE_CANDIDATE!>x[null] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[bar()] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[""] = nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
@@ -34,14 +34,14 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String, Int> = TreeMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>("", null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
<!INAPPLICABLE_CANDIDATE!>x[null] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[bar()] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[""] = nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
@@ -58,14 +58,14 @@ fun treeMapTest() {
fun concurrentHashMapTest() {
var x: ConcurrentHashMap<String, Int> = ConcurrentHashMap<String, Int>()
x.put(null, null)
x.put("", null)
x.put(bar(), 1)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>("", null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
<!INAPPLICABLE_CANDIDATE!>x[null] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[bar()] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[""] = nullableInt<!>
x[""] = 1
val b1: MutableMap<String, Int?> = x
@@ -9,14 +9,14 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String?, Int> = HashMap<String?, Int>()
x.put(null, null)
x.put("", null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>("", null)
x.put(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
<!INAPPLICABLE_CANDIDATE!>x[""] = nullableInt<!>
x[""] = 1
val b1: MutableMap<String?, Int?> = x
@@ -34,14 +34,14 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String?, Int> = TreeMap<String?, Int>()
x.put(null, null)
x.put("", null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>("", null)
x.put(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
x[""] = nullableInt
<!INAPPLICABLE_CANDIDATE!>x[""] = nullableInt<!>
x[""] = 1
val b1: MutableMap<String?, Int?> = x
@@ -9,13 +9,13 @@ val nullableInt: Int? = null
fun hashMapTest() {
var x: HashMap<String, Int?> = HashMap<String, Int?>()
x.put(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.put("", null)
x.put(bar(), 1)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
<!INAPPLICABLE_CANDIDATE!>x[null] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[bar()] = 1<!>
x[""] = nullableInt
x[""] = 1
@@ -33,13 +33,13 @@ fun hashMapTest() {
fun treeMapTest() {
var x: TreeMap<String, Int?> = TreeMap<String, Int?>()
x.put(null, null)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(null, null)
x.put("", null)
x.put(bar(), 1)
x.<!INAPPLICABLE_CANDIDATE!>put<!>(bar(), 1)
x.put("", 1)
x[null] = 1
x[bar()] = 1
<!INAPPLICABLE_CANDIDATE!>x[null] = 1<!>
<!INAPPLICABLE_CANDIDATE!>x[bar()] = 1<!>
x[""] = nullableInt
x[""] = 1
@@ -8,8 +8,8 @@ fun bar(): String? = null
fun fooHashSet() {
var x = HashSet<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
val b1: MutableSet<String?> = x
@@ -22,8 +22,8 @@ fun fooHashSet() {
fun fooTreeSet() {
var x = TreeSet<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
val b1: MutableSet<String?> = x
@@ -36,8 +36,8 @@ fun fooTreeSet() {
fun fooLinkedHashSet() {
var x = LinkedHashSet<String>()
x.add(null)
x.add(bar())
x.<!INAPPLICABLE_CANDIDATE!>add<!>(null)
x.<!INAPPLICABLE_CANDIDATE!>add<!>(bar())
x.add("")
val b1: MutableSet<String?> = x
@@ -2,7 +2,7 @@ fun foo(c : Collection<String>) = {
c.filter{
val s : String? = bar()
if (s == null) false // here!
zoo(s)
<!INAPPLICABLE_CANDIDATE!>zoo<!>(s)
}
}
@@ -3,7 +3,7 @@
fun indexOfMax(a: IntArray): Int? {
var maxI: Int? = 0
a.forEachIndexed { i, value ->
if (value >= a[maxI]) {
if (value >= <!INAPPLICABLE_CANDIDATE!>a[maxI]<!>) {
maxI = i
}
else if (value < 0) {