Implementation of smart casts for public / protected immutable properties that are not open and used in the same module.
DataFlowValueFactory and its environment refactoring: containing declaration is added into factory functions as an argument and used to determine identifier stability. A few minor fixes. #KT-5907 Fixed. #KT-4450 Fixed. #KT-4409 Fixed. New tests for KT-4409, KT-4450, KT-5907 (public and protected value properties used from the same module or not, open properties, variable properties, delegated properties, properties with non-default getter). Public val test and KT-362 test changed accordingly.
This commit is contained in:
@@ -5,8 +5,8 @@ package example
|
||||
|
||||
fun test() {
|
||||
val p = test.Public()
|
||||
if (p.public is Int) <!SMARTCAST_IMPOSSIBLE!>p.public<!> + 1
|
||||
if (p.<!INVISIBLE_MEMBER!>protected<!> is Int) <!SMARTCAST_IMPOSSIBLE!>p.<!INVISIBLE_MEMBER!>protected<!><!> + 1
|
||||
if (p.public is Int) <!DEBUG_INFO_SMARTCAST!>p.public<!> + 1
|
||||
if (p.<!INVISIBLE_MEMBER!>protected<!> is Int) <!DEBUG_INFO_SMARTCAST!>p.<!INVISIBLE_MEMBER!>protected<!><!> + 1
|
||||
if (p.internal is Int) <!DEBUG_INFO_SMARTCAST!>p.internal<!> + 1
|
||||
val i = test.Internal()
|
||||
if (i.public is Int) <!DEBUG_INFO_SMARTCAST!>i.public<!> + 1
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
public class A() {
|
||||
public val foo: Int? = 1
|
||||
public open class A() {
|
||||
public open val foo: Int? = 1
|
||||
}
|
||||
|
||||
fun Int.bar(i: Int) = i
|
||||
|
||||
fun test() {
|
||||
val p = A()
|
||||
// For open value properties, smart casts should not work
|
||||
if (p.foo is Int) <!SMARTCAST_IMPOSSIBLE!>p.foo<!> bar 11
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package
|
||||
internal fun test(): kotlin.Unit
|
||||
internal fun kotlin.Int.bar(/*0*/ i: kotlin.Int): kotlin.Int
|
||||
|
||||
public final class A {
|
||||
public open class A {
|
||||
public constructor A()
|
||||
public final val foo: kotlin.Int? = 1
|
||||
public open val foo: kotlin.Int? = 1
|
||||
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 @@
|
||||
public trait A {
|
||||
public val x: Any
|
||||
}
|
||||
|
||||
public class B(override public val x: Any) : A {
|
||||
fun foo(): Int {
|
||||
if (x is String) {
|
||||
return <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package
|
||||
|
||||
public trait A {
|
||||
public abstract val x: 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 final class B : A {
|
||||
public constructor B(/*0*/ x: kotlin.Any)
|
||||
public open override /*1*/ val x: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun foo(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
public class X {
|
||||
public val x : String? = null
|
||||
public fun fn(): Int {
|
||||
if (x != null)
|
||||
// Smartcast is possible because it's value property with default getter
|
||||
// used in the same module
|
||||
return <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public final class X {
|
||||
public constructor X()
|
||||
public final val x: kotlin.String? = null
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun fn(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
public class X {
|
||||
private val x : String? = null
|
||||
public val y: CharSequence?
|
||||
get() = x?.subSequence(0, 1)
|
||||
public fun fn(): Int {
|
||||
if (y != null)
|
||||
// With non-default getter smartcast is not possible
|
||||
return y<!UNSAFE_CALL!>.<!>length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public final class X {
|
||||
public constructor X()
|
||||
private final val x: kotlin.String? = null
|
||||
public final val y: kotlin.CharSequence?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun fn(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class Delegate {
|
||||
fun get(thisRef: Any?, prop: PropertyMetadata): String? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class Example {
|
||||
private val p: String? by Delegate()
|
||||
|
||||
public val r: String? = "xyz"
|
||||
|
||||
public fun foo(): String {
|
||||
// Smart cast is not possible if property is delegated
|
||||
return if (p != null) <!TYPE_MISMATCH!>p<!> else ""
|
||||
}
|
||||
|
||||
public fun bar(): String {
|
||||
// But is possible for non-delegated value property even if it's public
|
||||
return if (r != null) <!DEBUG_INFO_SMARTCAST!>r<!> else ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
internal final class Delegate {
|
||||
public constructor Delegate()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun get(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.PropertyMetadata): kotlin.String?
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class Example {
|
||||
public constructor Example()
|
||||
private final val p: kotlin.String?
|
||||
public final val r: kotlin.String? = "xyz"
|
||||
public final fun bar(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// MODULE: m1
|
||||
// FILE: a.kt
|
||||
|
||||
package a
|
||||
|
||||
public class X {
|
||||
public val x : String? = null
|
||||
}
|
||||
|
||||
// MODULE: m2(m1)
|
||||
// FILE: b.kt
|
||||
|
||||
package b
|
||||
|
||||
import a.X
|
||||
|
||||
public fun X.gav(): Int {
|
||||
if (x != null)
|
||||
// Smart cast is not possible if definition is in another module
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
|
||||
// FILE: c.kt
|
||||
|
||||
package a
|
||||
|
||||
public fun X.gav(): Int {
|
||||
if (x != null)
|
||||
// Even if it's in the same package
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// -- Module: <m1> --
|
||||
package
|
||||
|
||||
package a {
|
||||
|
||||
public final class X {
|
||||
public constructor X()
|
||||
public final val x: kotlin.String? = null
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- Module: <m2> --
|
||||
package
|
||||
|
||||
package a {
|
||||
public fun a.X.gav(): kotlin.Int
|
||||
|
||||
public final class X {
|
||||
// -- Module: <m1> --
|
||||
}
|
||||
}
|
||||
|
||||
package b {
|
||||
public fun a.X.gav(): kotlin.Int
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
public open class X {
|
||||
protected val x : String? = null
|
||||
public fun fn(): Int {
|
||||
if (x != null)
|
||||
// Smartcast is possible for protected value property in the same class
|
||||
return <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public class Y: X() {
|
||||
public fun bar(): Int {
|
||||
// Smartcast is possible even in derived class
|
||||
return if (x != null) <!DEBUG_INFO_SMARTCAST!>x<!>.length() else 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public open class X {
|
||||
public constructor X()
|
||||
protected final val x: kotlin.String? = null
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun fn(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Y : X {
|
||||
public constructor Y()
|
||||
protected final override /*1*/ /*fake_override*/ val x: kotlin.String?
|
||||
public final fun bar(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun fn(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
public class X {
|
||||
public var x : String? = null
|
||||
private var y: String? = "abc"
|
||||
public fun fn(): Int {
|
||||
if (x != null)
|
||||
// Smartcast is not possible for variable properties
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
else if (y != null)
|
||||
// Even if they are private
|
||||
return y<!UNSAFE_CALL!>.<!>length()
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public final class X {
|
||||
public constructor X()
|
||||
public final var x: kotlin.String?
|
||||
private final var y: kotlin.String?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun fn(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Reference in New Issue
Block a user