Support smart casts to Type after x as? Type null check #KT-4565 Fixed
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts
|
||||
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
if (a as? SomeSubClass != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a<!UNSAFE_CALL!>.<!>hashCode()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val b = (a as? SomeSubClass)?.foo
|
||||
if (b != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a<!UNSAFE_CALL!>.<!>hashCode()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val c = a as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'a' and 'c' can be cast to SomeSubClass
|
||||
a<!UNSAFE_CALL!>.<!>hashCode()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun g(/*0*/ a: SomeClass?): kotlin.Unit
|
||||
|
||||
public interface SomeClass {
|
||||
public abstract val data: kotlin.Any?
|
||||
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 interface SomeSubClass : SomeClass {
|
||||
public abstract override /*1*/ /*fake_override*/ val data: kotlin.Any?
|
||||
public abstract val foo: kotlin.Any?
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
if (a as? SomeSubClass != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.foo
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(a <!USELESS_CAST!>as SomeSubClass<!>).foo
|
||||
}
|
||||
val b = (a as? SomeSubClass)?.foo
|
||||
if (b != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.foo
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(a <!USELESS_CAST!>as SomeSubClass<!>).foo
|
||||
}
|
||||
val c = a as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'a' and 'c' can be cast to SomeSubClass
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.foo
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun g(/*0*/ a: SomeClass?): kotlin.Unit
|
||||
|
||||
public interface SomeClass {
|
||||
public abstract val data: kotlin.Any?
|
||||
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 interface SomeSubClass : SomeClass {
|
||||
public abstract override /*1*/ /*fake_override*/ val data: kotlin.Any?
|
||||
public abstract val foo: kotlin.Any?
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
// See KT-19007
|
||||
|
||||
// Stub
|
||||
fun String.indexOf(arg: String) = this.length - arg.length
|
||||
|
||||
// Stub
|
||||
fun String.toLowerCase() = this
|
||||
|
||||
fun foo(a: Any) {
|
||||
// Should compile in 1.2
|
||||
(a as? String)?.indexOf(<!DEBUG_INFO_SMARTCAST!>a<!>.toLowerCase())
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ a: kotlin.Any): kotlin.Unit
|
||||
public fun kotlin.String.indexOf(/*0*/ arg: kotlin.String): kotlin.Int
|
||||
public fun kotlin.String.toLowerCase(): kotlin.String
|
||||
@@ -0,0 +1,67 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
object Impl : SomeSubClass {
|
||||
override val data = ""
|
||||
override val foo = 42
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
var b = <!VARIABLE_WITH_REDUNDANT_INITIALIZER!>(a as? SomeSubClass)?.foo<!>
|
||||
b = "Hello"
|
||||
if (<!SENSELESS_COMPARISON!>b != null<!>) {
|
||||
// 'a' cannot be cast to SomeSubClass!
|
||||
a<!UNSAFE_CALL!>.<!>hashCode()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
var c = <!VARIABLE_WITH_REDUNDANT_INITIALIZER!>a as? SomeSubClass<!>
|
||||
c = Impl
|
||||
if (<!SENSELESS_COMPARISON!>c != null<!>) {
|
||||
// 'a' cannot be cast to SomeSubClass
|
||||
a<!UNSAFE_CALL!>.<!>hashCode()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.foo
|
||||
}
|
||||
}
|
||||
|
||||
fun f(a: SomeClass?) {
|
||||
var aa = a
|
||||
|
||||
if (aa as? SomeSubClass != null) {
|
||||
aa = null
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
<!DEBUG_INFO_CONSTANT!>aa<!><!UNSAFE_CALL!>.<!>hashCode()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(<!DEBUG_INFO_CONSTANT!>aa<!> as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(<!ALWAYS_NULL!>aa<!> as SomeSubClass).foo
|
||||
}
|
||||
val b = (aa as? SomeSubClass)?.foo
|
||||
aa = null
|
||||
if (b != null) {
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
<!DEBUG_INFO_CONSTANT!>aa<!><!UNSAFE_CALL!>.<!>hashCode()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(<!DEBUG_INFO_CONSTANT!>aa<!> as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
(<!ALWAYS_NULL!>aa<!> as SomeSubClass).foo
|
||||
}
|
||||
aa = a
|
||||
val c = aa as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'c' can be cast to SomeSubClass
|
||||
aa<!UNSAFE_CALL!>.<!>hashCode()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.hashCode()
|
||||
<!DEBUG_INFO_SMARTCAST!>c<!>.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public fun f(/*0*/ a: SomeClass?): kotlin.Unit
|
||||
public fun g(/*0*/ a: SomeClass?): kotlin.Unit
|
||||
|
||||
public object Impl : SomeSubClass {
|
||||
private constructor Impl()
|
||||
public open override /*1*/ val data: kotlin.String = ""
|
||||
public open override /*1*/ val foo: kotlin.Int = 42
|
||||
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 interface SomeClass {
|
||||
public abstract val data: kotlin.Any?
|
||||
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 interface SomeSubClass : SomeClass {
|
||||
public abstract override /*1*/ /*fake_override*/ val data: kotlin.Any?
|
||||
public abstract val foo: kotlin.Any?
|
||||
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
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts
|
||||
// A set of examples for
|
||||
// "If the result of a safe call is not null, understand that its receiver is not null"
|
||||
// and some other improvements for nullability detection
|
||||
|
||||
Reference in New Issue
Block a user