| // FILE: 1.kt |
| package foo |
| |
| fun fail(s: String): Nothing = throw Error(s) |
| |
| inline fun <T> depth1(a: Any?): T = a as T |
| |
| inline fun <T> depth2(a: Any?): T = depth1<T>(a) |
| |
| fun test() { |
| val t11 = depth1<String?>(null) |
| if (t11 != null) fail("t11") |
| val t12 = depth2<String?>(null) |
| if (t12 != null) fail("t12") |
| |
| val t21 = depth1<Nothing?>(null) |
| if (t21 != null) fail("t21") |
| val t22 = depth2<Nothing?>(null) |
| if (t22 != null) fail("t22") |
| |
| val t31 = depth1<String>("str1") |
| if (t31 != "str1") fail("t31") |
| val t32 = depth2<String>("str2") |
| if (t32 != "str2") fail("t32") |
| } |
| |
| |
| // From KT-60113 |
| fun kt60113() { |
| stupidRemembered = ComposerEmpty |
| crashes1_illegalcast() |
| stupidRemembered = ComposerEmpty |
| crashes2_unreachable() |
| stupidRemembered = ComposerEmpty |
| crash3_illegal_cast() |
| nocrash() |
| |
| val expectedInL = "BEFORE_CAST - null;Text1 = null;BEFORE_CAST - null;Text2 = null;BEFORE_CAST - asdasd;Text3 = asdasd;BEFORE_CAST - asdasd;Text0 = asdasd;" |
| if (l != expectedInL) fail("Unexpected value for l:$l") |
| } |
| |
| var l = "" |
| fun log(t: String?) { |
| l += t + ";" |
| } |
| |
| fun crashes1_illegalcast() { |
| val text = remember { |
| if (false) { |
| "asdasd" |
| } else { |
| null |
| } |
| } |
| |
| log("Text1 = $text") |
| } |
| |
| fun crashes2_unreachable() { |
| val text = remember { |
| if (false) { |
| null |
| } else { |
| null |
| } |
| } |
| |
| log("Text2 = $text") |
| } |
| |
| fun crash3_illegal_cast() { |
| val text = remember { |
| if (true) { |
| "asdasd" |
| } else { |
| "asda324234" |
| } |
| } |
| |
| log("Text3 = $text") |
| } |
| |
| fun nocrash() { |
| val text = cache(false) { |
| if (false) { |
| "asdasd" |
| } else { |
| null |
| } |
| } |
| |
| log("Text0 = $text") |
| } |
| |
| inline fun <T> remember(crossinline calculation: () -> T): T = |
| cache(false, calculation) |
| |
| inline fun <T> cache(invalid: Boolean, block: () -> T): T { |
| @Suppress("UNCHECKED_CAST") |
| return rememberedValue().let { |
| if (invalid || it === ComposerEmpty) { |
| val value = block() |
| stupidRemembered = value |
| value |
| } else it |
| }.also { log("BEFORE_CAST - $it") } as T |
| } |
| |
| fun rememberedValue(): Any? { |
| return stupidRemembered |
| } |
| |
| val ComposerEmpty = Any() |
| |
| var stupidRemembered: Any? = ComposerEmpty |
| |
| // FILE: 2.kt |
| package foo |
| |
| fun box(): String { |
| test() |
| kt60113() |
| |
| return "OK" |
| } |