Smart casts for local variables not captured in a closure and not changed in a loop, see #KT-3175.
isLocalVariable added. Assignment / initialization analysis. Control whether a variable is changed in a loop at the beginning and at the end of the loop. Control whether a variable is captured in a closure. #KT-3175 Fixed. #KT-2266 Fixed. Tests for variable null safety and for variables is/as operations. Loop / closure / variable property tests are included. Old tests changed in accordance with KT-3175. In particular, all three of testSmartcastImpossible were fixed.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
var v: String? = null
|
||||
v<!UNSAFE_CALL!>.<!>length()
|
||||
v = "abc"
|
||||
<!DEBUG_INFO_SMARTCAST!>v<!>.length()
|
||||
v = null
|
||||
v<!UNSAFE_CALL!>.<!>length()
|
||||
v = "abc"
|
||||
<!DEBUG_INFO_SMARTCAST!>v<!>.length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Unit
|
||||
@@ -0,0 +1,21 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething(): Boolean = true
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject) {
|
||||
var e: SomeObject?
|
||||
e = start
|
||||
do {
|
||||
// In theory smart cast is possible here
|
||||
// But in practice we have a loop with changing e
|
||||
// ?: should we "or" entrance type info with condition type info?
|
||||
if (!e<!UNSAFE_CALL!>.<!>doSomething())
|
||||
break
|
||||
// Smart cast here is still not possible
|
||||
e = e<!UNSAFE_CALL!>.<!>next()
|
||||
} while (e != null)
|
||||
// e can be null because of next()
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): kotlin.Unit
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(pp: String?): Int {
|
||||
var p = pp
|
||||
do {
|
||||
p!!.length()
|
||||
if (p == "abc") break
|
||||
p = null
|
||||
} while (!x())
|
||||
// Smart cast is NOT possible here
|
||||
return p<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ pp: kotlin.String?): kotlin.Int
|
||||
internal fun x(): kotlin.Boolean
|
||||
@@ -0,0 +1,16 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething() {}
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject): SomeObject {
|
||||
var e: SomeObject? = start
|
||||
for (i in 0..42) {
|
||||
// Unsafe calls because of nullable e at the beginning
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
e = e<!UNSAFE_CALL!>.<!>next()
|
||||
}
|
||||
// Smart cast is not possible here due to next()
|
||||
return <!TYPE_MISMATCH!>e<!>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): SomeObject
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething() {}
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject): SomeObject {
|
||||
var e: SomeObject? = start
|
||||
for (i in 0..42) {
|
||||
if (e == null)
|
||||
break
|
||||
// Smart casts are possible because of the break before
|
||||
<!DEBUG_INFO_SMARTCAST!>e<!>.doSomething()
|
||||
e = <!DEBUG_INFO_SMARTCAST!>e<!>.next()
|
||||
}
|
||||
return <!TYPE_MISMATCH!>e<!>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): SomeObject
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething() {}
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject): SomeObject {
|
||||
var e: SomeObject? = start
|
||||
for (i in 0..42) {
|
||||
if (e == null)
|
||||
continue
|
||||
// Smart casts are possible because of the continue before
|
||||
<!DEBUG_INFO_SMARTCAST!>e<!>.doSomething()
|
||||
e = <!DEBUG_INFO_SMARTCAST!>e<!>.next()
|
||||
}
|
||||
return <!TYPE_MISMATCH!>e<!>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): SomeObject
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public fun fooNotNull(s: String) {
|
||||
System.out.println("Length of $s is ${s.length()}")
|
||||
}
|
||||
|
||||
public fun foo() {
|
||||
var s: String? = "not null"
|
||||
if (s != null)
|
||||
fooNotNull(<!DEBUG_INFO_SMARTCAST!>s<!>)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
public fun fooNotNull(/*0*/ s: kotlin.String): kotlin.Unit
|
||||
@@ -0,0 +1,13 @@
|
||||
// See KT-5737
|
||||
fun get(): String? {
|
||||
return "abc"
|
||||
}
|
||||
|
||||
fun foo(): Int {
|
||||
var ss:String? = get()
|
||||
|
||||
return if (ss != null && <!DEBUG_INFO_SMARTCAST!>ss<!>.length() > 0)
|
||||
1
|
||||
else
|
||||
0
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
internal fun get(): kotlin.String?
|
||||
@@ -0,0 +1,12 @@
|
||||
public fun fooNotNull(s: String) {
|
||||
System.out.println("Length of $s is ${s.length()}")
|
||||
}
|
||||
|
||||
public fun foo() {
|
||||
var s: String? = "not null"
|
||||
if (s == null) {
|
||||
// Coming soon
|
||||
} else {
|
||||
fooNotNull(<!DEBUG_INFO_SMARTCAST!>s<!>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
public fun fooNotNull(/*0*/ s: kotlin.String): kotlin.Unit
|
||||
@@ -0,0 +1,11 @@
|
||||
public fun fooNotNull(s: String) {
|
||||
System.out.println("Length of $s is ${s.length()}")
|
||||
}
|
||||
|
||||
public fun foo() {
|
||||
var s: String? = "not null"
|
||||
if (s == null) {
|
||||
return
|
||||
}
|
||||
fooNotNull(<!DEBUG_INFO_SMARTCAST!>s<!>)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
public fun fooNotNull(/*0*/ s: kotlin.String): kotlin.Unit
|
||||
@@ -0,0 +1,21 @@
|
||||
// See KT-969
|
||||
fun f() {
|
||||
var s: String?
|
||||
s = "a"
|
||||
var s1 = "" // String – ?
|
||||
if (<!SENSELESS_COMPARISON!>s != null<!>) { // Redundant
|
||||
s1.length()
|
||||
// We can do smartcast here and below
|
||||
s1 = <!DEBUG_INFO_SMARTCAST!>s<!>.toString() // return String?
|
||||
s1.length()
|
||||
s1 = <!DEBUG_INFO_SMARTCAST!>s<!>
|
||||
s1.length()
|
||||
// It's just an assignment without smartcast
|
||||
val s2 = s
|
||||
// But smartcast can be done here
|
||||
<!DEBUG_INFO_SMARTCAST!>s2<!>.length()
|
||||
// And also here
|
||||
val s3 = <!DEBUG_INFO_SMARTCAST!>s<!>.toString()
|
||||
s3.length()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun f(): kotlin.Unit
|
||||
@@ -0,0 +1,20 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething(): Boolean = true
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject) {
|
||||
var e: SomeObject?
|
||||
e = start
|
||||
// This comparison is senseless
|
||||
while (e != null) {
|
||||
// Smart cast because of the loop condition
|
||||
if (!<!DEBUG_INFO_SMARTCAST!>e<!>.doSomething())
|
||||
break
|
||||
// We still have smart cast here despite of a break
|
||||
e = <!DEBUG_INFO_SMARTCAST!>e<!>.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): kotlin.Unit
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// See KT-774
|
||||
fun box() : Int {
|
||||
var a : Int? = 1
|
||||
var d = 1
|
||||
|
||||
if (a == null) {
|
||||
return 2
|
||||
} else {
|
||||
return <!DEBUG_INFO_SMARTCAST!>a<!> + d
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun box(): kotlin.Int
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
var v: String? = "xyz"
|
||||
// It is possible in principle to provide smart cast here
|
||||
v<!UNSAFE_CALL!>.<!>length()
|
||||
v = null
|
||||
v<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Unit
|
||||
@@ -0,0 +1,14 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething() {}
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
|
||||
fun list(start: SomeObject) {
|
||||
var e: SomeObject? = start
|
||||
while (e != null) {
|
||||
// While condition makes both smart casts possible
|
||||
<!DEBUG_INFO_SMARTCAST!>e<!>.doSomething()
|
||||
e = <!DEBUG_INFO_SMARTCAST!>e<!>.next()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): kotlin.Unit
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(pp: String?, rr: String?): Int {
|
||||
var p = pp
|
||||
var r = rr
|
||||
do {
|
||||
do {
|
||||
p!!.length()
|
||||
} while (r == null)
|
||||
} while (!x())
|
||||
// Auto cast possible
|
||||
<!DEBUG_INFO_SMARTCAST!>r<!>.length()
|
||||
// Auto cast possible
|
||||
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ pp: kotlin.String?, /*1*/ rr: kotlin.String?): kotlin.Int
|
||||
internal fun x(): kotlin.Boolean
|
||||
@@ -0,0 +1,19 @@
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(qq: String?): Int {
|
||||
var q = qq
|
||||
while(true) {
|
||||
q!!.length()
|
||||
var r = q
|
||||
do {
|
||||
var p = r
|
||||
do {
|
||||
// p = r, r = q and q is not null
|
||||
<!DEBUG_INFO_SMARTCAST!>p<!>.length()
|
||||
} while (!x())
|
||||
} while (<!SENSELESS_COMPARISON!>r == null<!>) // r = q and q is not null
|
||||
if (!x()) break
|
||||
}
|
||||
// Smart cast is possible
|
||||
return <!DEBUG_INFO_SMARTCAST!>q<!>.length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ qq: kotlin.String?): kotlin.Int
|
||||
internal fun x(): kotlin.Boolean
|
||||
@@ -0,0 +1,27 @@
|
||||
class Bar {
|
||||
fun next(): Bar? {
|
||||
if (2 == 4)
|
||||
return this
|
||||
else
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(): Bar {
|
||||
var x: Bar? = Bar()
|
||||
var y: Bar? = Bar()
|
||||
while (x != null) {
|
||||
// Here call is unsafe because of initialization and also inner loop
|
||||
y<!UNSAFE_CALL!>.<!>next()
|
||||
while (y != null) {
|
||||
if (x == y)
|
||||
// x is not null because of outer while
|
||||
return <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||
// y is not null because of inner while
|
||||
y = <!DEBUG_INFO_SMARTCAST!>y<!>.next()
|
||||
}
|
||||
// x is not null because of outer while
|
||||
x = <!DEBUG_INFO_SMARTCAST!>x<!>.next()
|
||||
}
|
||||
return Bar()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
internal fun foo(): Bar
|
||||
|
||||
internal final class Bar {
|
||||
public constructor 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
|
||||
internal final fun next(): Bar?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun String?.foo(): String {
|
||||
return this ?: ""
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
private var s: String? = null
|
||||
|
||||
fun bar(): String {
|
||||
s = "42"
|
||||
return s.foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
internal fun kotlin.String?.foo(): kotlin.String
|
||||
|
||||
internal final class MyClass {
|
||||
public constructor MyClass()
|
||||
private final var s: kotlin.String?
|
||||
internal final fun 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
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun String?.foo(): String {
|
||||
return this ?: ""
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
fun bar(): String {
|
||||
var s: String? = null
|
||||
if (4 < 2)
|
||||
s = "42"
|
||||
return s.foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
internal fun kotlin.String?.foo(): kotlin.String
|
||||
|
||||
internal final class MyClass {
|
||||
public constructor MyClass()
|
||||
internal final fun 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
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fun create(): Map<String, String> = null!!
|
||||
|
||||
fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> = null!!
|
||||
|
||||
fun <K, V> Map.Entry<K, V>.component1() = getKey()
|
||||
|
||||
fun <K, V> Map.Entry<K, V>.component2() = getValue()
|
||||
|
||||
class MyClass {
|
||||
private var m: Map<String, String>? = null
|
||||
fun foo(): Int {
|
||||
var res = 0
|
||||
m = create()
|
||||
// See KT-7428
|
||||
for ((k, v) in <!SMARTCAST_IMPOSSIBLE!>m<!>)
|
||||
res += (k.length() + v.length())
|
||||
return res
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun create(): kotlin.Map<kotlin.String, kotlin.String>
|
||||
internal fun </*0*/ K, /*1*/ V> kotlin.Map.Entry<K, V>.component1(): K
|
||||
internal fun </*0*/ K, /*1*/ V> kotlin.Map.Entry<K, V>.component2(): V
|
||||
internal fun </*0*/ K, /*1*/ V> kotlin.Map<K, V>.iterator(): kotlin.Iterator<kotlin.Map.Entry<K, V>>
|
||||
|
||||
internal final class MyClass {
|
||||
public constructor MyClass()
|
||||
private final var m: kotlin.Map<kotlin.String, kotlin.String>?
|
||||
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,17 @@
|
||||
public fun foo() {
|
||||
var s: String? = ""
|
||||
fun closure(): Int {
|
||||
if (s == "") {
|
||||
s = null
|
||||
return -1
|
||||
} else if (s == null) {
|
||||
return -2
|
||||
} else {
|
||||
return s<!UNSAFE_CALL!>.<!>length() // Here smartcast is possible, at least in principle
|
||||
}
|
||||
}
|
||||
if (s != null) {
|
||||
System.out.println(closure())
|
||||
System.out.println(s<!UNSAFE_CALL!>.<!>length()) // Here smartcast is not possible due to a closure predecessor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// See also KT-7186
|
||||
|
||||
fun IntArray.forEachIndexed( op: (i: Int, value: Int) -> Unit) {
|
||||
for (i in 0..this.size()-1)
|
||||
op(i, this[i])
|
||||
}
|
||||
|
||||
fun max(a: IntArray): Int? {
|
||||
var maxI: Int? = null
|
||||
a.forEachIndexed { i, value ->
|
||||
if (maxI == null || value >= a[<!TYPE_MISMATCH!>maxI<!>])
|
||||
maxI = i
|
||||
}
|
||||
return maxI
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun max(/*0*/ a: kotlin.IntArray): kotlin.Int?
|
||||
internal fun kotlin.IntArray.forEachIndexed(/*0*/ op: (kotlin.Int, kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||
@@ -0,0 +1,15 @@
|
||||
public fun foo() {
|
||||
var s: String? = ""
|
||||
fun closure(): Int {
|
||||
if (s == null) {
|
||||
return -1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
if (s != null) {
|
||||
System.out.println(closure())
|
||||
// Smart cast is possible but closure makes it harder to understand
|
||||
System.out.println(s<!UNSAFE_CALL!>.<!>length())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
@@ -0,0 +1,9 @@
|
||||
public fun foo() {
|
||||
var i: Int? = 1
|
||||
if (i != null) {
|
||||
while (i != 10) {
|
||||
<!UNUSED_CHANGED_VALUE!>i<!UNSAFE_CALL!>++<!><!> // Here smart cast should not be performed due to a successor
|
||||
i = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
@@ -0,0 +1,9 @@
|
||||
fun get(): String? {
|
||||
return ""
|
||||
}
|
||||
|
||||
fun foo(): Int {
|
||||
var c: String? = get()
|
||||
c!!.length()
|
||||
return <!DEBUG_INFO_SMARTCAST!>c<!>.length() // Previous line should make !! unnecessary here.
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
internal fun get(): kotlin.String?
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(): Int {
|
||||
var i: Int? = <!VARIABLE_WITH_REDUNDANT_INITIALIZER!>42<!>
|
||||
i = null
|
||||
return i <!UNSAFE_INFIX_CALL!>+<!> 1
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
@@ -0,0 +1,8 @@
|
||||
public fun foo() {
|
||||
var i: Int? = 1
|
||||
if (i != null) {
|
||||
while (i != 10) {
|
||||
<!DEBUG_INFO_SMARTCAST!>i<!>++
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(): Int {
|
||||
var s: String? = <!VARIABLE_WITH_REDUNDANT_INITIALIZER!>"abc"<!>
|
||||
s = null
|
||||
return s<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
@@ -0,0 +1,13 @@
|
||||
fun x(): Boolean { return true }
|
||||
|
||||
public fun foo(pp: String?): Int {
|
||||
var p = pp
|
||||
while(true) {
|
||||
p!!.length()
|
||||
if (x()) break
|
||||
p = null
|
||||
}
|
||||
// Smart cast is NOT possible here
|
||||
// (we could provide it but p = null makes it much harder)
|
||||
return p<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ pp: kotlin.String?): kotlin.Int
|
||||
internal fun x(): kotlin.Boolean
|
||||
@@ -0,0 +1,17 @@
|
||||
data class SomeObject(val n: SomeObject?) {
|
||||
fun doSomething(): Boolean = true
|
||||
fun next(): SomeObject? = n
|
||||
}
|
||||
|
||||
fun list(start: SomeObject) {
|
||||
var e: SomeObject? = start
|
||||
while (e != null) {
|
||||
// Smart cast due to the loop condition
|
||||
if (!<!DEBUG_INFO_SMARTCAST!>e<!>.doSomething())
|
||||
break
|
||||
// We still have smart cast here despite of a break
|
||||
e = <!DEBUG_INFO_SMARTCAST!>e<!>.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
internal fun list(/*0*/ start: SomeObject): kotlin.Unit
|
||||
|
||||
kotlin.data() internal final class SomeObject {
|
||||
public constructor SomeObject(/*0*/ n: SomeObject?)
|
||||
internal final val n: SomeObject?
|
||||
internal final /*synthesized*/ fun component1(): SomeObject?
|
||||
public final /*synthesized*/ fun copy(/*0*/ n: SomeObject? = ...): SomeObject
|
||||
internal final fun doSomething(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun next(): SomeObject?
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Reference in New Issue
Block a user