== fn == fun fn() : String? = null --------------------- L0: 1 r(null) -> ret(*|) L1 L1: NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == let == inline fun T.let(f: (T) -> R): R = f(this) --------------------- L0: 1 v(f: (T) -> R) magic[FAKE_INITIALIZER](f: (T) -> R) -> w(f|) r(f) -> r(this, ) -> mark(f(this)) call(f(this), invoke|, ) -> ret(*|) L1 L1: NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == foo == fun foo(): String { val x = fn()?.let { throw Exception() } ?: "unreachable?" return x } --------------------- L0: 1 2 mark({ val x = fn()?.let { throw Exception() } ?: "unreachable?" return x }) v(val x = fn()?.let { throw Exception() } ?: "unreachable?") mark(fn()?.let { throw Exception() }) jf(L2) NEXT:[mark(fn()?.let { throw Exception() } ?: "unreachable?"), mark(fn())] mark(fn()) call(fn(), fn) -> mark({ throw Exception() }) jmp?(L3) NEXT:[r({ throw Exception() }) -> , d({ throw Exception() })] d({ throw Exception() }) NEXT:[] L3 [after local declaration]: r({ throw Exception() }) -> PREV:[jmp?(L3)] mark(let { throw Exception() }) call(let { throw Exception() }, let|, ) -> L2 [result of call]: mark(fn()?.let { throw Exception() } ?: "unreachable?") PREV:[jf(L2), call(let { throw Exception() }, let|, ) -> ] jt(L6|) NEXT:[mark("unreachable?"), merge(fn()?.let { throw Exception() } ?: "unreachable?"|, ) -> ] mark("unreachable?") r("unreachable?") -> L6 [after elvis operator]: merge(fn()?.let { throw Exception() } ?: "unreachable?"|, ) -> PREV:[jt(L6|), r("unreachable?") -> ] w(x|) r(x) -> ret(*|) L1 L1: 1 NEXT:[] error: PREV:[] sink: PREV:[, , d({ throw Exception() })] ===================== == anonymous_0 == { throw Exception() } --------------------- L4: 3 4 mark(throw Exception()) mark(throw Exception()) mark(Exception()) call(Exception(), ) -> throw (throw Exception()|) NEXT:[] - 3 ret(*|!) L5 PREV:[] L5: NEXT:[] PREV:[] error: PREV:[throw (throw Exception()|)] sink: PREV:[, ] ===================== == bar == fun bar(): String { val x = fn() ?: return "" val y = x?.let { throw Exception() } ?: "unreachable" return y } --------------------- L0: 1 2 mark({ val x = fn() ?: return "" val y = x?.let { throw Exception() } ?: "unreachable" return y }) v(val x = fn() ?: return "") mark(fn()) call(fn(), fn) -> mark(fn() ?: return "") jt(L2|) NEXT:[mark(""), merge(fn() ?: return ""|, !) -> ] mark("") r("") -> ret(*|) L1 NEXT:[] L2 [after elvis operator]: merge(fn() ?: return ""|, !) -> PREV:[jt(L2|)] w(x|) v(val y = x?.let { throw Exception() } ?: "unreachable") mark(x?.let { throw Exception() }) jf(L3) NEXT:[jmp(error), r(x) -> ] r(x) -> mark({ throw Exception() }) jmp?(L4) NEXT:[r({ throw Exception() }) -> , d({ throw Exception() })] d({ throw Exception() }) NEXT:[] L4 [after local declaration]: r({ throw Exception() }) -> PREV:[jmp?(L4)] mark(let { throw Exception() }) call(let { throw Exception() }, let|, ) -> jmp(error) NEXT:[] L3 [result of call]: jmp(error) NEXT:[] PREV:[jf(L3)] - mark(x?.let { throw Exception() } ?: "unreachable") PREV:[] - jt(L7|) NEXT:[mark("unreachable"), merge(x?.let { throw Exception() } ?: "unreachable"|, ) -> ] PREV:[] - mark("unreachable") PREV:[] - r("unreachable") -> PREV:[] L7 [after elvis operator]: - merge(x?.let { throw Exception() } ?: "unreachable"|, ) -> PREV:[] - w(y|) PREV:[] - r(y) -> PREV:[] - ret(*|) L1 PREV:[] L1: 1 NEXT:[] PREV:[ret(*|) L1] error: PREV:[jmp(error), jmp(error)] sink: PREV:[, , d({ throw Exception() })] ===================== == anonymous_1 == { throw Exception() } --------------------- L5: 3 4 mark(throw Exception()) mark(throw Exception()) mark(Exception()) call(Exception(), ) -> throw (throw Exception()|) NEXT:[] - 3 ret(*|!) L6 PREV:[] L6: NEXT:[] PREV:[] error: PREV:[throw (throw Exception()|)] sink: PREV:[, ] =====================