d652dc620c
^KT-55231 Fixed ^KTIJ-21012 Fixed
91 lines
2.4 KiB
Kotlin
Vendored
91 lines
2.4 KiB
Kotlin
Vendored
// !DUMP_CFG
|
|
import kotlin.contracts.*
|
|
|
|
fun <T> n(): T? = null
|
|
|
|
@OptIn(ExperimentalContracts::class)
|
|
fun <T> run2(x: () -> T, y: () -> T) {
|
|
contract {
|
|
callsInPlace(x, InvocationKind.EXACTLY_ONCE)
|
|
callsInPlace(y, InvocationKind.EXACTLY_ONCE)
|
|
}
|
|
x()
|
|
y()
|
|
}
|
|
|
|
fun test1(x: String?) {
|
|
var p = x
|
|
if (p != null) {
|
|
run2(
|
|
{ p = null; n() },
|
|
{ <!SMARTCAST_IMPOSSIBLE!>p<!>.length; 123 } // Bad: may or may not not be called first
|
|
)
|
|
p<!UNSAFE_CALL!>.<!>length // Bad: p = null
|
|
}
|
|
}
|
|
|
|
fun test1_tail(x: String?) {
|
|
var p = x
|
|
if (p != null) {
|
|
run2({ p = null; n() }) {
|
|
<!SMARTCAST_IMPOSSIBLE!>p<!>.length // Bad: may or may not not be called first
|
|
123
|
|
}
|
|
p<!UNSAFE_CALL!>.<!>length // Bad: p = null
|
|
}
|
|
}
|
|
|
|
fun test2(x: Any?) {
|
|
var p: Any? = x
|
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
|
run2({ p = null; n() }, { p as String; 123 })
|
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad: p is Nothing? | (String & Nothing?) = Nothing?
|
|
p?.<!UNRESOLVED_REFERENCE!>length<!> // Technically OK because p is null, but what is "length"?
|
|
}
|
|
|
|
fun test3(x: Any?) {
|
|
var p: Any? = x
|
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
|
run2({ p = null; n() }, { p = ""; 123 })
|
|
p<!UNSAFE_CALL!>.<!>length // Bad: p can be null
|
|
p?.length // OK: p is String | Nothing? = String?
|
|
}
|
|
|
|
interface I1 { val x: Int }
|
|
interface I2 { val y: Int }
|
|
|
|
fun test4(x: Any?) {
|
|
x.<!UNRESOLVED_REFERENCE!>x<!> // Bad
|
|
x.<!UNRESOLVED_REFERENCE!>y<!> // Bad
|
|
run2(
|
|
{ x as I1; x.<!UNRESOLVED_REFERENCE!>y<!>; n() }, // Bad: may or may not be called first
|
|
{ x as I2; x.<!UNRESOLVED_REFERENCE!>x<!>; 123 } // Bad: may or may not be called first
|
|
)
|
|
x.x // OK: x is I1 & I2
|
|
x.y // OK: x is I1 & I2
|
|
}
|
|
|
|
fun test5(x: Any?, q: String?) {
|
|
var p: Any? = x
|
|
p.<!UNRESOLVED_REFERENCE!>length<!> // Bad
|
|
run2({ p as Int; 123 }, { p = q; n() })
|
|
p<!UNSAFE_CALL!>.<!>length // Bad: p is String? | (String? & Int) = String?
|
|
p?.length // OK: p is String?
|
|
}
|
|
|
|
fun test6() {
|
|
val x: String
|
|
// not necessarily initialized in second lambda (may call in any order)
|
|
run2({ x = ""; x.length }, { <!UNINITIALIZED_VARIABLE!>x<!>.length })
|
|
x.length // initialized here
|
|
}
|
|
|
|
fun test7() {
|
|
val x: Any? = ""
|
|
val y: Any?
|
|
run2({ y = x }, { })
|
|
if (y is String) {
|
|
x.length // ok - aliased
|
|
}
|
|
}
|