Call chains: receiver data flow info is dropped for extensions with nullable receiver #KT-10056 Fixed
This commit is contained in:
+2
-3
@@ -1,6 +1,5 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list, despite of a chain
|
||||
x?.subList(0, 1)<!UNSAFE_CALL!>.<!>get(<!DEBUG_INFO_SMARTCAST!>x<!>.size)
|
||||
// But not here!
|
||||
// x is not-null only inside subList
|
||||
x?.subList(0, <!DEBUG_INFO_SMARTCAST!>x<!>.size - 1)<!UNSAFE_CALL!>.<!>get(x<!UNSAFE_CALL!>.<!>size)
|
||||
return x!!.size
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// See KT-10056
|
||||
class Foo(val bar: String)
|
||||
|
||||
public inline fun <T, R> T.let(f: (T) -> R): R = f(this)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo?.bar.let {
|
||||
// Error, foo?.bar is nullable
|
||||
it<!UNSAFE_CALL!>.<!>length
|
||||
// Error, foo is nullable
|
||||
foo<!UNSAFE_CALL!>.<!>bar.length
|
||||
// Correct
|
||||
foo?.bar?.length
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ foo: Foo?): kotlin.Unit
|
||||
public inline fun </*0*/ T, /*1*/ R> T.let(/*0*/ f: (T) -> R): R
|
||||
|
||||
public final class Foo {
|
||||
public constructor Foo(/*0*/ bar: kotlin.String)
|
||||
public final val bar: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
class Bar(val gav: String)
|
||||
|
||||
class Foo(val bar: Bar, val nbar: Bar?) {
|
||||
fun baz(s: String) = if (s != "") Bar(s) else null
|
||||
}
|
||||
|
||||
public inline fun <T, R> T.let(f: (T) -> R): R = f(this)
|
||||
|
||||
fun String?.call(f: (String?) -> String?) = f(this)
|
||||
|
||||
fun String.notNullLet(f: (String) -> Unit) = f(this)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo?.bar?.gav.let {
|
||||
// Error, foo?.bar?.gav is nullable
|
||||
it<!UNSAFE_CALL!>.<!>length
|
||||
// Error, foo is nullable
|
||||
foo<!UNSAFE_CALL!>.<!>bar.gav.length
|
||||
// Correct
|
||||
foo?.bar?.gav?.length
|
||||
}
|
||||
foo?.bar?.gav.call { it }?.notNullLet {
|
||||
foo<!UNSAFE_CALL!>.<!>hashCode()
|
||||
foo<!UNSAFE_CALL!>.<!>bar.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun testNotNull(foo: Foo) {
|
||||
val s: String? = ""
|
||||
foo.baz(s!!)?.gav.let {
|
||||
it<!UNSAFE_CALL!>.<!>length
|
||||
// Ok because of foo.
|
||||
<!DEBUG_INFO_SMARTCAST!>s<!>.length.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun testNullable(foo: Foo?) {
|
||||
val s: String? = ""
|
||||
foo?.baz(s!!)?.gav.let {
|
||||
it<!UNSAFE_CALL!>.<!>length
|
||||
// Ok because of foo?.
|
||||
s?.length?.hashCode()
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ foo: Foo?): kotlin.Unit
|
||||
public fun testNotNull(/*0*/ foo: Foo): kotlin.Unit
|
||||
public fun testNullable(/*0*/ foo: Foo?): kotlin.Unit
|
||||
public fun kotlin.String?.call(/*0*/ f: (kotlin.String?) -> kotlin.String?): kotlin.String?
|
||||
public inline fun </*0*/ T, /*1*/ R> T.let(/*0*/ f: (T) -> R): R
|
||||
public fun kotlin.String.notNullLet(/*0*/ f: (kotlin.String) -> kotlin.Unit): kotlin.Unit
|
||||
|
||||
public final class Bar {
|
||||
public constructor Bar(/*0*/ gav: kotlin.String)
|
||||
public final val gav: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Foo {
|
||||
public constructor Foo(/*0*/ bar: Bar, /*1*/ nbar: Bar?)
|
||||
public final val bar: Bar
|
||||
public final val nbar: Bar?
|
||||
public final fun baz(/*0*/ s: kotlin.String): Bar?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class Foo(val bar: String?)
|
||||
|
||||
public inline fun <T, R> T.let(f: (T) -> R): R = f(this)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo!!.bar.let {
|
||||
// Correct
|
||||
<!DEBUG_INFO_SMARTCAST!>foo<!>.bar?.length
|
||||
// Unnecessary
|
||||
foo<!UNNECESSARY_SAFE_CALL!>?.<!>bar?.length
|
||||
}
|
||||
<!DEBUG_INFO_SMARTCAST!>foo<!>.bar?.length
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ foo: Foo?): kotlin.Unit
|
||||
public inline fun </*0*/ T, /*1*/ R> T.let(/*0*/ f: (T) -> R): R
|
||||
|
||||
public final class Foo {
|
||||
public constructor Foo(/*0*/ bar: kotlin.String?)
|
||||
public final val bar: kotlin.String?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// FILE: Foo.java
|
||||
public class Foo {
|
||||
public String bar;
|
||||
|
||||
private Foo(String bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
public static Foo create(String bar) {
|
||||
return new Foo(bar);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Test.kt
|
||||
public inline fun <T, R> T.let(f: (T) -> R): R = f(this)
|
||||
|
||||
fun test() {
|
||||
val foo = Foo.create(null)
|
||||
foo?.bar.let {
|
||||
// Error, foo?.bar is nullable
|
||||
it<!UNSAFE_CALL!>.<!>length
|
||||
// Foo is nullable but flexible, so call is considered safe here
|
||||
foo.bar.length
|
||||
// Correct
|
||||
foo?.bar?.length
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
public inline fun </*0*/ T, /*1*/ R> T.let(/*0*/ f: (T) -> R): R
|
||||
|
||||
public open class Foo {
|
||||
private constructor Foo(/*0*/ bar: kotlin.String!)
|
||||
public final var bar: kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun create(/*0*/ bar: kotlin.String!): Foo!
|
||||
}
|
||||
Reference in New Issue
Block a user