Effects: add cfg-tests on inlined lambdas

==========
Introduction of Effect System: 15/18
This commit is contained in:
Dmitry Savvinov
2017-10-03 15:02:50 +03:00
parent a986999226
commit f487525a1d
48 changed files with 6677 additions and 860 deletions
@@ -0,0 +1,299 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== getBoolean ==
fun getBoolean(): Boolean = false
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(false) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== test ==
fun test() {
val x: Int
if (getBoolean())
myRun {
while (getBoolean()) {
do {
myRun {
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
break
} while (getBoolean())
myRun { x.inc() }
myRun { x = 42 }
break
}
x = 42
}
else
myRun {
x = 42
}
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }) INIT: in: {x=D} out: {x=D}
mark(getBoolean())
call(getBoolean(), getBoolean) -> <v0>
jf(L2|<v0>)
mark({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 })
r({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) -> <v1>
mark(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 })
call(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }, myRun|<v1>) -> <v2>
L3 [before inlined declaration]:
inlined({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L4 [after inlined declaration]:
jmp(L31) USE: in: {x=READ} out: {x=READ}
L2 [else branch]:
mark({ x = 42 }) INIT: in: {x=D} out: {x=D}
r({ x = 42 }) -> <v3>
mark(myRun { x = 42 })
call(myRun { x = 42 }, myRun|<v3>) -> <v4>
L32 [before inlined declaration]:
inlined({ x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L31 ['if' expression result]:
L33 [after inlined declaration]:
merge(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }|<v2>, <v4>) -> <v5>
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v6> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v6>) -> <v7>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
while (getBoolean()) {
do {
myRun {
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
break
} while (getBoolean())
myRun { x.inc() }
myRun { x = 42 }
break
}
x = 42
}
---------------------
L5:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42)
L7 [loop entry point]:
L11 [condition entry point]:
mark(getBoolean())
call(getBoolean(), getBoolean) -> <v0>
mark(while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break })
jf(L8|<v0>)
L9 [body entry point]:
5 mark({ do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break })
6 mark(do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()))
L12 [loop entry point]:
L14 [body entry point]:
mark({ myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break })
mark({ if (getBoolean()) { x = 42 } else { x = 43 } })
r({ if (getBoolean()) { x = 42 } else { x = 43 } }) -> <v1>
mark(myRun { if (getBoolean()) { x = 42 } else { x = 43 } })
call(myRun { if (getBoolean()) { x = 42 } else { x = 43 } }, myRun|<v1>) -> <v2>
L17 [before inlined declaration]:
inlined({ if (getBoolean()) { x = 42 } else { x = 43 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L18 [after inlined declaration]:
jmp(L13) USE: in: {x=READ} out: {x=READ}
L15 [body exit point]:
L16 [condition entry point]:
- mark(getBoolean())
- call(getBoolean(), getBoolean) -> <v4>
- 5 jt(L12|<v4>)
L13 [loop exit point]:
read (Unit) INIT: in: {x=ID} out: {x=ID}
mark({ x.inc() })
r({ x.inc() }) -> <v5>
mark(myRun { x.inc() })
call(myRun { x.inc() }, myRun|<v5>) -> <v6>
L23 [before inlined declaration]:
inlined({ x.inc() }) USE: in: {x=READ} out: {x=READ}
L24 [after inlined declaration]:
mark({ x = 42 })
r({ x = 42 }) -> <v7>
mark(myRun { x = 42 })
call(myRun { x = 42 }, myRun|<v7>) -> <v8>
L27 [before inlined declaration]:
inlined({ x = 42 })
L28 [after inlined declaration]:
jmp(L8) USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
- 4 jmp(L7)
L8 [loop exit point]:
L10 [body exit point]:
read (Unit) INIT: in: {x=I?D} out: {x=I?D}
r(42) -> <v10> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v10>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L6:
3 <END> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
== inlined anonymous_2 ==
{
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
---------------------
L19:
7 <START> INIT: in: {x=D} out: {x=D}
8 mark(if (getBoolean()) { x = 42 } else { x = 43 })
mark(if (getBoolean()) { x = 42 } else { x = 43 })
mark(getBoolean())
call(getBoolean(), getBoolean) -> <v0>
jf(L21|<v0>)
9 mark({ x = 42 })
r(42) -> <v1> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v1>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
8 jmp(L22) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
L21 [else branch]:
9 mark({ x = 43 }) INIT: in: {x=D} out: {x=D}
r(43) -> <v3> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v3>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L22 ['if' expression result]:
8 merge(if (getBoolean()) { x = 42 } else { x = 43 }|!<v2>, !<v4>) -> <v5> INIT: in: {x=ID} out: {x=ID}
L20:
7 <END> USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
== inlined anonymous_3 ==
{ x.inc() }
---------------------
L25:
6 <START> INIT: in: {x=ID} out: {x=ID}
7 mark(x.inc())
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ}
mark(inc())
call(inc(), inc|<v0>) -> <v1>
6 ret(*|<v1>) L26
L26:
<END> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
=====================
== inlined anonymous_4 ==
{ x = 42 }
---------------------
L29:
6 <START> INIT: in: {x=ID} out: {x=ID}
7 mark(x = 42)
r(42) -> <v0>
w(x|<v0>)
L30:
6 <END> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
=====================
== inlined anonymous_5 ==
{
x = 42
}
---------------------
L34:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(x = 42)
r(42) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L35:
3 <END> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,43 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun getBoolean(): Boolean = false
fun test() {
val x: Int
if (getBoolean())
myRun {
while (getBoolean()) {
do {
myRun {
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
break
} while (getBoolean())
myRun { x.inc() }
myRun { x = 42 }
break
}
x = 42
}
else
myRun {
x = 42
}
x.inc()
}
@@ -0,0 +1,157 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== getBoolean ==
fun getBoolean(): Boolean = false
---------------------
false <v0>: Boolean NEW: r(false) -> <v0>
=====================
== test ==
fun test() {
val x: Int
if (getBoolean())
myRun {
while (getBoolean()) {
do {
myRun {
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
break
} while (getBoolean())
myRun { x.inc() }
myRun { x = 42 }
break
}
x = 42
}
else
myRun {
x = 42
}
x.inc()
}
---------------------
getBoolean() <v0>: Boolean NEW: call(getBoolean(), getBoolean) -> <v0>
{ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } <v1>: {<: () -> Unit} NEW: r({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) -> <v1>
myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } <v2>: * NEW: call(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }, myRun|<v1>) -> <v2>
{ x = 42 } <v3>: {<: () -> Unit} NEW: r({ x = 42 }) -> <v3>
myRun { x = 42 } <v4>: * NEW: call(myRun { x = 42 }, myRun|<v3>) -> <v4>
if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } <v5>: * NEW: merge(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }|<v2>, <v4>) -> <v5>
x <v6>: Int NEW: r(x) -> <v6>
inc() <v7>: * NEW: call(inc(), inc|<v6>) -> <v7>
x.inc() <v7>: * COPY
{ val x: Int if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } x.inc() } <v7>: * COPY
=====================
== inlined anonymous_1 ==
{
while (getBoolean()) {
do {
myRun {
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
break
} while (getBoolean())
myRun { x.inc() }
myRun { x = 42 }
break
}
x = 42
}
---------------------
getBoolean() <v0>: Boolean NEW: call(getBoolean(), getBoolean) -> <v0>
{ if (getBoolean()) { x = 42 } else { x = 43 } } <v1>: {<: () -> Unit} NEW: r({ if (getBoolean()) { x = 42 } else { x = 43 } }) -> <v1>
myRun { if (getBoolean()) { x = 42 } else { x = 43 } } <v2>: * NEW: call(myRun { if (getBoolean()) { x = 42 } else { x = 43 } }, myRun|<v1>) -> <v2>
break !<v3>: *
{ myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } !<v3>: * COPY
getBoolean() <v4>: Boolean NEW: call(getBoolean(), getBoolean) -> <v4>
{ x.inc() } <v5>: {<: () -> Int} NEW: r({ x.inc() }) -> <v5>
myRun { x.inc() } <v6>: * NEW: call(myRun { x.inc() }, myRun|<v5>) -> <v6>
{ x = 42 } <v7>: {<: () -> Unit} NEW: r({ x = 42 }) -> <v7>
myRun { x = 42 } <v8>: * NEW: call(myRun { x = 42 }, myRun|<v7>) -> <v8>
break !<v9>: *
{ do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } !<v9>: * COPY
42 <v10>: Int NEW: r(42) -> <v10>
x = 42 !<v11>: *
while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 !<v11>: * COPY
=====================
== inlined anonymous_2 ==
{
if (getBoolean()) {
x = 42
}
else {
x = 43
}
}
---------------------
getBoolean() <v0>: Boolean NEW: call(getBoolean(), getBoolean) -> <v0>
42 <v1>: Int NEW: r(42) -> <v1>
x = 42 !<v2>: *
{ x = 42 } !<v2>: * COPY
43 <v3>: Int NEW: r(43) -> <v3>
x = 43 !<v4>: *
{ x = 43 } !<v4>: * COPY
if (getBoolean()) { x = 42 } else { x = 43 } <v5>: * NEW: merge(if (getBoolean()) { x = 42 } else { x = 43 }|!<v2>, !<v4>) -> <v5>
if (getBoolean()) { x = 42 } else { x = 43 } <v5>: * COPY
=====================
== inlined anonymous_3 ==
{ x.inc() }
---------------------
x <v0>: Int NEW: r(x) -> <v0>
inc() <v1>: Int NEW: call(inc(), inc|<v0>) -> <v1>
x.inc() <v1>: Int COPY
x.inc() <v1>: Int COPY
=====================
== inlined anonymous_4 ==
{ x = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
x = 42 !<v1>: *
x = 42 !<v1>: * COPY
=====================
== inlined anonymous_5 ==
{
x = 42
}
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
x = 42 !<v1>: *
x = 42 !<v1>: * COPY
=====================
@@ -0,0 +1,96 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== test ==
fun test() {
myRun { throw java.lang.IllegalArgumentException() }
val x: Int = 42
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
2 mark({ myRun { throw java.lang.IllegalArgumentException() } val x: Int = 42 })
mark({ throw java.lang.IllegalArgumentException() })
r({ throw java.lang.IllegalArgumentException() }) -> <v0>
mark(myRun { throw java.lang.IllegalArgumentException() })
call(myRun { throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ throw java.lang.IllegalArgumentException() }) USE: in: {} out: {}
L3 [after inlined declaration]:
- v(val x: Int = 42)
- r(42) -> <v2>
- w(x|<v2>)
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{ throw java.lang.IllegalArgumentException() }
---------------------
L4:
3 <START> INIT: in: {} out: {}
4 mark(throw java.lang.IllegalArgumentException())
mark(throw java.lang.IllegalArgumentException())
mark(java.lang.IllegalArgumentException())
mark(IllegalArgumentException())
call(IllegalArgumentException(), <init>) -> <v0>
throw (throw java.lang.IllegalArgumentException()|<v0>) USE: in: {} out: {}
L5:
- 3 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> USE: in: {} out: {}
=====================
@@ -0,0 +1,15 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
fun test() {
myRun { throw java.lang.IllegalArgumentException() }
val x: Int = 42
}
@@ -0,0 +1,45 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: * NEW: call(block(), invoke|<v3>) -> <v4>
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } <v4>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== test ==
fun test() {
myRun { throw java.lang.IllegalArgumentException() }
val x: Int = 42
}
---------------------
{ throw java.lang.IllegalArgumentException() } <v0>: {<: () -> Unit} NEW: r({ throw java.lang.IllegalArgumentException() }) -> <v0>
myRun { throw java.lang.IllegalArgumentException() } <v1>: * NEW: call(myRun { throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
42 <v2>: Int NEW: r(42) -> <v2>
=====================
== inlined anonymous_1 ==
{ throw java.lang.IllegalArgumentException() }
---------------------
IllegalArgumentException() <v0>: {<: Throwable} NEW: call(IllegalArgumentException(), <init>) -> <v0>
java.lang.IllegalArgumentException() <v0>: {<: Throwable} COPY
throw java.lang.IllegalArgumentException() !<v1>: *
throw java.lang.IllegalArgumentException() !<v1>: * COPY
=====================
@@ -0,0 +1,145 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== unknownRun ==
inline fun unknownRun(block: () -> Unit) { block() }
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ block() }) INIT: in: {} out: {}
r(block) -> <v1>
mark(block())
call(block(), invoke|<v1>) -> <v2>
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== foo ==
fun foo() {
val x: Int
myRun {
unknownRun { println("shouldn't change anything") }
x = 42
}
println(x)
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int myRun { unknownRun { println("shouldn't change anything") } x = 42 } println(x) })
v(val x: Int) INIT: in: {} out: {x=D}
mark({ unknownRun { println("shouldn't change anything") } x = 42 }) INIT: in: {x=D} out: {x=D}
r({ unknownRun { println("shouldn't change anything") } x = 42 }) -> <v0>
mark(myRun { unknownRun { println("shouldn't change anything") } x = 42 })
call(myRun { unknownRun { println("shouldn't change anything") } x = 42 }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ unknownRun { println("shouldn't change anything") } x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
L3 [after inlined declaration]:
r(x) -> <v2> USE: in: {} out: {x=READ}
mark(println(x))
call(println(x), println|<v2>) -> <v3>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
unknownRun { println("shouldn't change anything") }
x = 42
}
---------------------
L4:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(unknownRun { println("shouldn't change anything") } x = 42)
mark({ println("shouldn't change anything") })
jmp?(L6)
d({ println("shouldn't change anything") }) INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ}
L6 [after local declaration]:
r({ println("shouldn't change anything") }) -> <v0> INIT: in: {x=D} out: {x=D}
mark(unknownRun { println("shouldn't change anything") })
call(unknownRun { println("shouldn't change anything") }, unknownRun|<v0>) -> <v1>
r(42) -> <v2> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v2>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L5:
3 <END> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ}
=====================
== anonymous_2 ==
{ println("shouldn't change anything") }
---------------------
L7:
5 <START> INIT: in: {x=D} out: {x=D}
6 mark(println("shouldn't change anything"))
mark("shouldn't change anything")
r("shouldn't change anything") -> <v0>
mark(println("shouldn't change anything"))
call(println("shouldn't change anything"), println|<v0>) -> <v1>
L8:
5 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,21 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
inline fun unknownRun(block: () -> Unit) { block() }
fun foo() {
val x: Int
myRun {
unknownRun { println("shouldn't change anything") }
x = 42
}
println(x)
}
@@ -0,0 +1,71 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: Unit NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== unknownRun ==
inline fun unknownRun(block: () -> Unit) { block() }
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
block <v1>: {<: () -> Unit} NEW: r(block) -> <v1>
block() <v2>: * NEW: call(block(), invoke|<v1>) -> <v2>
{ block() } <v2>: * COPY
=====================
== foo ==
fun foo() {
val x: Int
myRun {
unknownRun { println("shouldn't change anything") }
x = 42
}
println(x)
}
---------------------
{ unknownRun { println("shouldn't change anything") } x = 42 } <v0>: {<: () -> Unit} NEW: r({ unknownRun { println("shouldn't change anything") } x = 42 }) -> <v0>
myRun { unknownRun { println("shouldn't change anything") } x = 42 } <v1>: * NEW: call(myRun { unknownRun { println("shouldn't change anything") } x = 42 }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
println(x) <v3>: * NEW: call(println(x), println|<v2>) -> <v3>
{ val x: Int myRun { unknownRun { println("shouldn't change anything") } x = 42 } println(x) } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
unknownRun { println("shouldn't change anything") }
x = 42
}
---------------------
{ println("shouldn't change anything") } <v0>: {<: () -> Unit} NEW: r({ println("shouldn't change anything") }) -> <v0>
unknownRun { println("shouldn't change anything") } <v1>: * NEW: call(unknownRun { println("shouldn't change anything") }, unknownRun|<v0>) -> <v1>
42 <v2>: Int NEW: r(42) -> <v2>
x = 42 !<v3>: *
unknownRun { println("shouldn't change anything") } x = 42 !<v3>: * COPY
=====================
== anonymous_2 ==
{ println("shouldn't change anything") }
---------------------
"shouldn't change anything" <v0>: * NEW: r("shouldn't change anything") -> <v0>
println("shouldn't change anything") <v1>: * NEW: call(println("shouldn't change anything"), println|<v0>) -> <v1>
println("shouldn't change anything") <v1>: * COPY
=====================
@@ -0,0 +1,339 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== innerComputation ==
fun innerComputation(): Int = 42
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(42) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== outerComputation ==
fun outerComputation(): Int = 52
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(52) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== log ==
fun log() = Unit
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(Unit) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== outerFinallyInitializes ==
fun outerFinallyInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
} catch (e: java.lang.Exception) {
log()
}
// possible reassignment if innerComputation finished
x = 42
}
// Definite reassignment here, cause can get here only if myRun finished
x = outerComputation()
} catch (e: java.lang.Exception) {
// can catch exception thrown by the inner, so x can be not initalized
log()
} finally {
// Possible reassignment (e.g. if everything finished)
x = 42
}
// Properly initialized
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } // Properly initialized x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }) INIT: in: {x=D} out: {x=D}
jmp?(L2)
jmp?(L3)
3 mark({ myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() })
mark({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 })
r({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) -> <v0>
mark(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 })
call(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }, myRun|<v0>) -> <v1>
L4 [before inlined declaration]:
inlined({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) INIT: in: {x=ID} out: {x=ID}
L5 [after inlined declaration]:
mark(outerComputation())
call(outerComputation(), outerComputation) -> <v2>
w(x|<v2>)
2 jmp?(L2)
jmp?(L3)
jmp(L10)
L2 [onException]:
3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v4>) INIT: in: {x=I?D} out: {x=I?D}
4 mark({ // can catch exception thrown by the inner, so x can be not initalized log() }) INIT: in: {x=I?D} out: {x=I?D}
mark(log())
call(log(), log) -> <v5>
3 jmp(L10)
L10 [afterCatches]:
2 jmp(L11) USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L3 [onExceptionToFinallyBlock]:
L12 [start finally]:
3 mark({ // Possible reassignment (e.g. if everything finished) x = 42 })
r(42) -> <v6> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
w(x|<v6>) INIT: in: {x=I?D} out: {x=ID} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ}
L13 [finish finally]:
2 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
L11 [skipFinallyToErrorBlock]:
L14 [copy of L3, onExceptionToFinallyBlock]:
3 mark({ // Possible reassignment (e.g. if everything finished) x = 42 }) INIT: in: {x=I?D} out: {x=I?D}
r(42) -> <v6> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v6>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
2 merge(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }|!<v3>, <v5>) -> <v8> INIT: in: {x=ID} out: {x=ID}
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v9> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v9>) -> <v10>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
try {
x = innerComputation()
} catch (e: java.lang.Exception) {
log()
}
// possible reassignment if innerComputation finished
x = 42
}
---------------------
L6:
4 <START> INIT: in: {x=D} out: {x=D}
5 mark(try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42)
mark(try { x = innerComputation() } catch (e: java.lang.Exception) { log() })
jmp?(L8)
6 mark({ x = innerComputation() })
mark(innerComputation())
call(innerComputation(), innerComputation) -> <v0>
w(x|<v0>) INIT: in: {x=D} out: {x=ID}
5 jmp?(L8) INIT: in: {x=ID} out: {x=ID}
jmp(L9)
L8 [onException]:
6 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v2> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v2>) INIT: in: {x=I?D} out: {x=I?D}
7 mark({ log() }) INIT: in: {x=I?D} out: {x=I?D}
mark(log())
call(log(), log) -> <v3>
6 jmp(L9)
L9 [afterCatches]:
5 merge(try { x = innerComputation() } catch (e: java.lang.Exception) { log() }|!<v1>, <v3>) -> <v4>
r(42) -> <v5>
w(x|<v5>) INIT: in: {x=I?D} out: {x=ID}
L7:
4 <END> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
=====================
== innerFinalltInitializes ==
fun innerFinalltInitializes() {
val x: Int
try {
myRun {
try {
innerComputation()
} catch (e: java.lang.Exception) {
log()
} finally {
x = 42
}
}
// Properly initialized
x.inc()
} catch (e: java.lang.Exception) {
log()
}
// Still can be non-initialized (e.g. if x.inc() threw an exception)
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } // Still can be non-initialized (e.g. if x.inc() threw an exception) x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }) INIT: in: {x=D} out: {x=D}
jmp?(L2) USE: in: {x=READ} out: {x=READ}
3 mark({ myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() })
mark({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } })
r({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) -> <v0>
mark(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } })
call(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }, myRun|<v0>) -> <v1>
L3 [before inlined declaration]:
inlined({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L4 [after inlined declaration]:
mark(x.inc())
r(x) -> <v2>
mark(inc())
call(inc(), inc|<v2>) -> <v3>
2 jmp?(L2)
jmp(L14)
L2 [onException]:
3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v4>) INIT: in: {x=I?D} out: {x=I?D}
4 mark({ log() }) INIT: in: {x=I?D} out: {x=I?D}
mark(log())
call(log(), log) -> <v5>
3 jmp(L14)
L14 [afterCatches]:
2 merge(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }|<v3>, <v5>) -> <v6>
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v7> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v7>) -> <v8>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_2 ==
{
try {
innerComputation()
} catch (e: java.lang.Exception) {
log()
} finally {
x = 42
}
}
---------------------
L5:
4 <START> INIT: in: {x=D} out: {x=D}
5 mark(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 })
mark(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 })
jmp?(L7)
jmp?(L8)
6 mark({ innerComputation() })
mark(innerComputation())
call(innerComputation(), innerComputation) -> <v0>
5 jmp?(L7)
jmp?(L8)
jmp(L9)
L7 [onException]:
6 v(e: java.lang.Exception) INIT: in: {x=D} out: {x=D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v1> INIT: in: {x=D} out: {x=D}
w(e|<v1>) INIT: in: {x=D} out: {x=D}
7 mark({ log() }) INIT: in: {x=D} out: {x=D}
mark(log())
call(log(), log) -> <v2>
6 jmp(L9)
L9 [afterCatches]:
5 jmp(L10)
L8 [onExceptionToFinallyBlock]:
L11 [start finally]:
6 mark({ x = 42 })
r(42) -> <v3> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v3>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L12 [finish finally]:
5 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
L10 [skipFinallyToErrorBlock]:
L13 [copy of L8, onExceptionToFinallyBlock]:
6 mark({ x = 42 }) INIT: in: {x=D} out: {x=D}
r(42) -> <v3> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v3>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
5 merge(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }|<v0>, <v2>) -> <v5> INIT: in: {x=ID} out: {x=ID}
4 ret(*|<v5>) L6
L6:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,66 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun innerComputation(): Int = 42
fun outerComputation(): Int = 52
fun log() = Unit
fun outerFinallyInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
} catch (e: java.lang.Exception) {
log()
}
// possible reassignment if innerComputation finished
x = 42
}
// Definite reassignment here, cause can get here only if myRun finished
x = outerComputation()
} catch (e: java.lang.Exception) {
// can catch exception thrown by the inner, so x can be not initalized
log()
} finally {
// Possible reassignment (e.g. if everything finished)
x = 42
}
// Properly initialized
x.inc()
}
fun innerFinalltInitializes() {
val x: Int
try {
myRun {
try {
innerComputation()
} catch (e: java.lang.Exception) {
log()
} finally {
x = 42
}
}
// Properly initialized
x.inc()
} catch (e: java.lang.Exception) {
log()
}
// Still can be non-initialized (e.g. if x.inc() threw an exception)
x.inc()
}
@@ -0,0 +1,172 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== innerComputation ==
fun innerComputation(): Int = 42
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
=====================
== outerComputation ==
fun outerComputation(): Int = 52
---------------------
52 <v0>: Int NEW: r(52) -> <v0>
=====================
== log ==
fun log() = Unit
---------------------
Unit <v0>: Unit NEW: r(Unit) -> <v0>
=====================
== outerFinallyInitializes ==
fun outerFinallyInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
} catch (e: java.lang.Exception) {
log()
}
// possible reassignment if innerComputation finished
x = 42
}
// Definite reassignment here, cause can get here only if myRun finished
x = outerComputation()
} catch (e: java.lang.Exception) {
// can catch exception thrown by the inner, so x can be not initalized
log()
} finally {
// Possible reassignment (e.g. if everything finished)
x = 42
}
// Properly initialized
x.inc()
}
---------------------
<v4>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4>
{ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } <v0>: {<: () -> Unit} NEW: r({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) -> <v0>
myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } <v1>: * NEW: call(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }, myRun|<v0>) -> <v1>
outerComputation() <v2>: Int NEW: call(outerComputation(), outerComputation) -> <v2>
x = outerComputation() !<v3>: *
{ myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } !<v3>: * COPY
log() <v5>: * NEW: call(log(), log) -> <v5>
{ // can catch exception thrown by the inner, so x can be not initalized log() } <v5>: * COPY
42 <v6>: Int NEW: r(42) -> <v6>
x = 42 !<v7>: *
{ // Possible reassignment (e.g. if everything finished) x = 42 } !<v7>: * COPY
try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } <v8>: * NEW: merge(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }|!<v3>, <v5>) -> <v8>
x <v9>: Int NEW: r(x) -> <v9>
inc() <v10>: * NEW: call(inc(), inc|<v9>) -> <v10>
x.inc() <v10>: * COPY
{ val x: Int try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } // Properly initialized x.inc() } <v10>: * COPY
=====================
== inlined anonymous_1 ==
{
try {
x = innerComputation()
} catch (e: java.lang.Exception) {
log()
}
// possible reassignment if innerComputation finished
x = 42
}
---------------------
<v2>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v2>
innerComputation() <v0>: Int NEW: call(innerComputation(), innerComputation) -> <v0>
x = innerComputation() !<v1>: *
{ x = innerComputation() } !<v1>: * COPY
log() <v3>: * NEW: call(log(), log) -> <v3>
{ log() } <v3>: * COPY
try { x = innerComputation() } catch (e: java.lang.Exception) { log() } <v4>: * NEW: merge(try { x = innerComputation() } catch (e: java.lang.Exception) { log() }|!<v1>, <v3>) -> <v4>
42 <v5>: Int NEW: r(42) -> <v5>
x = 42 !<v6>: *
try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 !<v6>: * COPY
=====================
== innerFinalltInitializes ==
fun innerFinalltInitializes() {
val x: Int
try {
myRun {
try {
innerComputation()
} catch (e: java.lang.Exception) {
log()
} finally {
x = 42
}
}
// Properly initialized
x.inc()
} catch (e: java.lang.Exception) {
log()
}
// Still can be non-initialized (e.g. if x.inc() threw an exception)
x.inc()
}
---------------------
<v4>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4>
{ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } <v0>: {<: () -> Any} NEW: r({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) -> <v0>
myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } <v1>: * NEW: call(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } <v3>: * COPY
log() <v5>: * NEW: call(log(), log) -> <v5>
{ log() } <v5>: * COPY
try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } <v6>: * NEW: merge(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }|<v3>, <v5>) -> <v6>
x <v7>: Int NEW: r(x) -> <v7>
inc() <v8>: * NEW: call(inc(), inc|<v7>) -> <v8>
x.inc() <v8>: * COPY
{ val x: Int try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } // Still can be non-initialized (e.g. if x.inc() threw an exception) x.inc() } <v8>: * COPY
=====================
== inlined anonymous_2 ==
{
try {
innerComputation()
} catch (e: java.lang.Exception) {
log()
} finally {
x = 42
}
}
---------------------
<v1>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v1>
innerComputation() <v0>: {<: Any} NEW: call(innerComputation(), innerComputation) -> <v0>
{ innerComputation() } <v0>: {<: Any} COPY
log() <v2>: {<: Any} NEW: call(log(), log) -> <v2>
{ log() } <v2>: {<: Any} COPY
42 <v3>: Int NEW: r(42) -> <v3>
x = 42 !<v4>: *
{ x = 42 } !<v4>: * COPY
try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } <v5>: {<: Any} NEW: merge(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }|<v0>, <v2>) -> <v5>
try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } <v5>: {<: Any} COPY
=====================
@@ -0,0 +1,211 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== innerComputation ==
fun innerComputation(): Int = 42
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(42) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== outerComputation ==
fun outerComputation(): Int = 52
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(52) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== innerTryCatchInitializes ==
fun innerTryCatchInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
x.inc()
}
catch (e: java.lang.Exception) {
/** Potential reassignment because x.inc() could threw */
x = 42
x.inc()
}
}
// Can get here only when inlined lambda exited properly, i.e. x is initialized
x.inc()
outerComputation()
} catch (e: java.lang.Exception) {
// Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized)
// OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok)
// So, x=I? here
x.inc()
// Potential reasignment
x = 42
}
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }) INIT: in: {x=D} out: {x=D}
jmp?(L2) USE: in: {x=READ} out: {x=READ}
3 mark({ myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() })
mark({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } })
r({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) -> <v0>
mark(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } })
call(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }, myRun|<v0>) -> <v1>
L3 [before inlined declaration]:
inlined({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L4 [after inlined declaration]:
mark(x.inc())
r(x) -> <v2>
mark(inc())
call(inc(), inc|<v2>) -> <v3>
mark(outerComputation())
call(outerComputation(), outerComputation) -> <v4>
2 jmp?(L2)
jmp(L9)
L2 [onException]:
3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v5> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v5>) INIT: in: {x=I?D} out: {x=I?D}
4 mark({ // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }) INIT: in: {x=I?D} out: {x=I?D}
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v6> USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ}
mark(inc())
call(inc(), inc|<v6>) -> <v7>
r(42) -> <v8> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v8>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
3 jmp(L9) INIT: in: {x=ID} out: {x=ID}
L9 [afterCatches]:
2 merge(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }|<v4>, !<v9>) -> <v10>
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v11> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v11>) -> <v12>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
try {
x = innerComputation()
x.inc()
}
catch (e: java.lang.Exception) {
/** Potential reassignment because x.inc() could threw */
x = 42
x.inc()
}
}
---------------------
L5:
4 <START> INIT: in: {x=D} out: {x=D}
5 mark(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() })
mark(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() })
jmp?(L7)
6 mark({ x = innerComputation() x.inc() })
mark(innerComputation())
call(innerComputation(), innerComputation) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc()) INIT: in: {x=ID} out: {x=ID}
r(x) -> <v1>
mark(inc())
call(inc(), inc|<v1>) -> <v2>
5 jmp?(L7)
jmp(L8) USE: in: {x=READ} out: {x=READ}
L7 [onException]:
6 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v3>) INIT: in: {x=I?D} out: {x=I?D}
7 mark({ /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }) INIT: in: {x=I?D} out: {x=I?D}
r(42) -> <v4> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v4>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc()) INIT: in: {x=ID} out: {x=ID}
r(x) -> <v5>
mark(inc())
call(inc(), inc|<v5>) -> <v6>
6 jmp(L8)
L8 [afterCatches]:
5 merge(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }|<v2>, <v6>) -> <v7>
4 ret(*|<v7>) L6
L6:
<END> USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,45 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun innerComputation(): Int = 42
fun outerComputation(): Int = 52
fun innerTryCatchInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
x.inc()
}
catch (e: java.lang.Exception) {
/** Potential reassignment because x.inc() could threw */
x = 42
x.inc()
}
}
// Can get here only when inlined lambda exited properly, i.e. x is initialized
x.inc()
outerComputation()
} catch (e: java.lang.Exception) {
// Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized)
// OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok)
// So, x=I? here
x.inc()
// Potential reasignment
x = 42
}
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
x.inc()
}
@@ -0,0 +1,118 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== innerComputation ==
fun innerComputation(): Int = 42
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
=====================
== outerComputation ==
fun outerComputation(): Int = 52
---------------------
52 <v0>: Int NEW: r(52) -> <v0>
=====================
== innerTryCatchInitializes ==
fun innerTryCatchInitializes() {
val x: Int
try {
myRun {
try {
x = innerComputation()
x.inc()
}
catch (e: java.lang.Exception) {
/** Potential reassignment because x.inc() could threw */
x = 42
x.inc()
}
}
// Can get here only when inlined lambda exited properly, i.e. x is initialized
x.inc()
outerComputation()
} catch (e: java.lang.Exception) {
// Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized)
// OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok)
// So, x=I? here
x.inc()
// Potential reasignment
x = 42
}
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
x.inc()
}
---------------------
<v5>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v5>
{ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } <v0>: {<: () -> Int} NEW: r({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) -> <v0>
myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } <v1>: * NEW: call(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
outerComputation() <v4>: * NEW: call(outerComputation(), outerComputation) -> <v4>
{ myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } <v4>: * COPY
x <v6>: Int NEW: r(x) -> <v6>
inc() <v7>: * NEW: call(inc(), inc|<v6>) -> <v7>
x.inc() <v7>: * COPY
42 <v8>: Int NEW: r(42) -> <v8>
x = 42 !<v9>: *
{ // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } !<v9>: * COPY
try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } <v10>: * NEW: merge(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }|<v4>, !<v9>) -> <v10>
x <v11>: Int NEW: r(x) -> <v11>
inc() <v12>: * NEW: call(inc(), inc|<v11>) -> <v12>
x.inc() <v12>: * COPY
{ val x: Int try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) x.inc() } <v12>: * COPY
=====================
== inlined anonymous_1 ==
{
try {
x = innerComputation()
x.inc()
}
catch (e: java.lang.Exception) {
/** Potential reassignment because x.inc() could threw */
x = 42
x.inc()
}
}
---------------------
<v3>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3>
innerComputation() <v0>: Int NEW: call(innerComputation(), innerComputation) -> <v0>
x <v1>: Int NEW: r(x) -> <v1>
inc() <v2>: Int NEW: call(inc(), inc|<v1>) -> <v2>
x.inc() <v2>: Int COPY
{ x = innerComputation() x.inc() } <v2>: Int COPY
42 <v4>: Int NEW: r(42) -> <v4>
x <v5>: Int NEW: r(x) -> <v5>
inc() <v6>: Int NEW: call(inc(), inc|<v5>) -> <v6>
x.inc() <v6>: Int COPY
{ /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } <v6>: Int COPY
try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } <v7>: Int NEW: merge(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }|<v2>, <v6>) -> <v7>
try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } <v7>: Int COPY
=====================
@@ -0,0 +1,148 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(false) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== withLabeledReturn ==
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(y: Int) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](y: Int) -> <v0> INIT: in: {} out: {}
w(y|<v0>) INIT: in: {} out: {}
2 mark({ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) }) INIT: in: {} out: {}
v(val x = myRun outer@ { myRun { return@outer Unit } println(y) }) INIT: in: {} out: {}
mark(outer@ { myRun { return@outer Unit } println(y) }) INIT: in: {} out: {}
mark({ myRun { return@outer Unit } println(y) })
r({ myRun { return@outer Unit } println(y) }) -> <v1>
mark(myRun outer@ { myRun { return@outer Unit } println(y) })
call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|<v1>) -> <v2>
L2 [before inlined declaration]:
inlined({ myRun { return@outer Unit } println(y) })
L3 [after inlined declaration]:
w(x|<v2>) INIT: in: {} out: {}
r(y) -> <v3> INIT: in: {} out: {}
mark(println(y))
call(println(y), println|<v3>) -> <v4>
r(x) -> <v5>
mark(println(x))
call(println(x), println|<v5>) -> <v6>
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
myRun { return@outer Unit }
println(y)
}
---------------------
L4:
3 <START> INIT: in: {} out: {}
4 mark(myRun { return@outer Unit } println(y))
mark({ return@outer Unit })
r({ return@outer Unit }) -> <v0>
mark(myRun { return@outer Unit })
call(myRun { return@outer Unit }, myRun|<v0>) -> <v1>
L6 [before inlined declaration]:
inlined({ return@outer Unit }) USE: in: {} out: {}
L7 [after inlined declaration]:
- r(y) -> <v2>
- mark(println(y))
- call(println(y), println|<v2>) -> <v3>
L5:
3 <END> INIT: in: {} out: {} USE: in: {} out: {}
error:
- <ERROR>
sink:
<SINK> INIT: in: {} out: {} USE: in: {} out: {}
=====================
== inlined anonymous_2 ==
{ return@outer Unit }
---------------------
L8:
5 <START> INIT: in: {} out: {}
6 mark(return@outer Unit)
r(Unit) -> <v0>
ret(*|<v0>) L5 USE: in: {} out: {}
L9:
- 5 <END>
error:
- <ERROR>
sink:
- <SINK>
=====================
@@ -0,0 +1,22 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun getBool(): Boolean = false
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
@@ -0,0 +1,73 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: Unit NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
false <v0>: Boolean NEW: r(false) -> <v0>
=====================
== withLabeledReturn ==
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](y: Int) -> <v0>
{ myRun { return@outer Unit } println(y) } <v1>: {<: () -> Unit} NEW: r({ myRun { return@outer Unit } println(y) }) -> <v1>
outer@ { myRun { return@outer Unit } println(y) } <v1>: {<: () -> Unit} COPY
myRun outer@ { myRun { return@outer Unit } println(y) } <v2>: Unit NEW: call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|<v1>) -> <v2>
y <v3>: Int NEW: r(y) -> <v3>
println(y) <v4>: * NEW: call(println(y), println|<v3>) -> <v4>
x <v5>: * NEW: r(x) -> <v5>
println(x) <v6>: * NEW: call(println(x), println|<v5>) -> <v6>
{ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) } <v6>: * COPY
=====================
== inlined anonymous_1 ==
{
myRun { return@outer Unit }
println(y)
}
---------------------
{ return@outer Unit } <v0>: {<: () -> Unit} NEW: r({ return@outer Unit }) -> <v0>
myRun { return@outer Unit } <v1>: * NEW: call(myRun { return@outer Unit }, myRun|<v0>) -> <v1>
y <v2>: Int NEW: r(y) -> <v2>
println(y) <v3>: * NEW: call(println(y), println|<v2>) -> <v3>
myRun { return@outer Unit } println(y) <v3>: * COPY
=====================
== inlined anonymous_2 ==
{ return@outer Unit }
---------------------
Unit <v0>: Unit NEW: r(Unit) -> <v0>
return@outer Unit !<v1>: *
return@outer Unit !<v1>: * COPY
=====================
@@ -0,0 +1,243 @@
== callsAndInverts ==
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(b: Boolean) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](b: Boolean) -> <v0> INIT: in: {} out: {}
w(b|<v0>) INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v1> INIT: in: {} out: {}
w(block|<v1>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> <v2>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|<v2>) -> <v3>
r(block) -> <v4>
mark(block())
call(block(), invoke|<v4>) -> <v5>
r(b) -> <v6>
mark(!b)
call(!b, not|<v6>) -> <v7>
ret(*|<v7>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b)
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
magic[IMPLICIT_RECEIVER](returns(true)) -> <v4>
r(true) -> <v5>
mark(returns(true))
call(returns(true), returns|<v4>, <v5>) -> <v6>
mark((!b))
r(b) -> <v7>
mark(!b)
call(!b, not|<v7>) -> <v8>
mark(returns(true) implies (!b))
call(returns(true) implies (!b), implies|<v6>, <v8>) -> <v9>
magic[IMPLICIT_RECEIVER](returns(false)) -> <v10>
r(false) -> <v11>
mark(returns(false))
call(returns(false), returns|<v10>, <v11>) -> <v12>
r(b) -> <v13>
mark(returns(false) implies b)
call(returns(false) implies b, implies|<v12>, <v13>) -> <v14>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== smartcastAndInitialization ==
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(x: Any?) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](x: Any?) -> <v0> INIT: in: {} out: {}
w(x|<v0>) INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) }) INIT: in: {} out: {}
v(val y: Int) INIT: in: {} out: {y=D}
mark(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }) INIT: in: {y=D} out: {y=D}
mark(x !is String)
r(x) -> <v1>
magic[IS](x !is String|<v1>) -> <v2>
mark({ y = 42 })
r({ y = 42 }) -> <v3>
mark(callsAndInverts(x !is String) { y = 42 })
call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v2>, <v3>) -> <v4>
L2 [before inlined declaration]:
inlined({ y = 42 }) INIT: in: {y=ID} out: {y=ID} USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ}
L3 [after inlined declaration]:
jf(L6|<v4>)
3 mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })
r(y) -> <v5>
mark(println(y))
call(println(y), println|<v5>) -> <v6>
magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v7>
mark(!DEBUG_INFO_SMARTCAST)
call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v7>) -> <v8>
2 jmp(L7)
L6 [else branch]:
3 mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> })
r(y) -> <v9>
mark(println(y))
call(println(y), println|<v9>) -> <v10>
mark(x.<)
r(x) -> <v11>
magic[UNSUPPORTED_ELEMENT](x.<|<v11>) -> <v12>
L7 ['if' expression result]:
2 merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v8>, <v12>) -> <v13> USE: in: {y=READ} out: {y=READ}
r(y) -> <v14> USE: in: {} out: {y=READ}
mark(println(y))
call(println(y), println|<v14>) -> <v15>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{ y = 42 }
---------------------
L4:
3 <START> INIT: in: {y=D} out: {y=D}
4 mark(y = 42)
r(42) -> <v0> USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ}
w(y|<v0>) INIT: in: {y=D} out: {y=ID} USE: in: {y=READ} out: {y=WRITTEN_AFTER_READ}
L5:
3 <END> INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ}
=====================
== inPresenceOfLazy ==
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(x: Any?) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](x: Any?) -> <v0> INIT: in: {} out: {}
w(x|<v0>) INIT: in: {} out: {}
v(unknownBoolean: Boolean) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> <v1> INIT: in: {} out: {}
w(unknownBoolean|<v1>) INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) }) INIT: in: {} out: {}
v(val y: Int) INIT: in: {} out: {y=D}
mark(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }) INIT: in: {y=D} out: {y=D}
r(unknownBoolean) -> <v2>
jf(L2|<v2>) USE: in: {y=READ} out: {y=READ}
mark(x !is String)
r(x) -> <v3>
magic[IS](x !is String|<v3>) -> <v4>
mark({ y = 42 })
r({ y = 42 }) -> <v5>
mark(callsAndInverts(x !is String) { y = 42 })
call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v4>, <v5>) -> <v6>
L3 [before inlined declaration]:
inlined({ y = 42 }) INIT: in: {y=ID} out: {y=ID} USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ}
L2 [result of boolean operation]:
L4 [after inlined declaration]:
magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|<v2>, <v6>) -> <v7> INIT: in: {y=I?D} out: {y=I?D}
jf(L7|<v7>)
3 mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })
r(y) -> <v8>
mark(println(y))
call(println(y), println|<v8>) -> <v9>
magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v10>
mark(!DEBUG_INFO_SMARTCAST)
call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v10>) -> <v11>
2 jmp(L8)
L7 [else branch]:
3 mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> })
r(y) -> <v12>
mark(println(y))
call(println(y), println|<v12>) -> <v13>
mark(x.<)
r(x) -> <v14>
magic[UNSUPPORTED_ELEMENT](x.<|<v14>) -> <v15>
L8 ['if' expression result]:
2 merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v11>, <v15>) -> <v16> USE: in: {y=READ} out: {y=READ}
r(y) -> <v17> USE: in: {} out: {y=READ}
mark(println(y))
call(println(y), println|<v17>) -> <v18>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_2 ==
{ y = 42 }
---------------------
L5:
3 <START> INIT: in: {y=D} out: {y=D}
4 mark(y = 42)
r(42) -> <v0> USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ}
w(y|<v0>) INIT: in: {y=D} out: {y=ID} USE: in: {y=READ} out: {y=WRITTEN_AFTER_READ}
L6:
3 <END> INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ}
=====================
@@ -0,0 +1,44 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
@@ -0,0 +1,136 @@
== callsAndInverts ==
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
---------------------
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0>
<v1>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v1>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } <v2>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> <v2>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } <v3>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|<v2>) -> <v3>
block <v4>: {<: () -> Unit} NEW: r(block) -> <v4>
block() <v5>: * NEW: call(block(), invoke|<v4>) -> <v5>
b <v6>: Boolean NEW: r(b) -> <v6>
!b <v7>: Boolean NEW: call(!b, not|<v6>) -> <v7>
return !b !<v8>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b } !<v8>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
<v10>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(false)) -> <v10>
<v4>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(true)) -> <v4>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
true <v5>: * NEW: r(true) -> <v5>
returns(true) <v6>: {<: SimpleEffect} NEW: call(returns(true), returns|<v4>, <v5>) -> <v6>
b <v7>: Boolean NEW: r(b) -> <v7>
!b <v8>: Boolean NEW: call(!b, not|<v7>) -> <v8>
(!b) <v8>: Boolean COPY
returns(true) implies (!b) <v9>: * NEW: call(returns(true) implies (!b), implies|<v6>, <v8>) -> <v9>
false <v11>: * NEW: r(false) -> <v11>
returns(false) <v12>: {<: SimpleEffect} NEW: call(returns(false), returns|<v10>, <v11>) -> <v12>
b <v13>: Boolean NEW: r(b) -> <v13>
returns(false) implies b <v14>: * NEW: call(returns(false) implies b, implies|<v12>, <v13>) -> <v14>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b <v14>: * COPY
=====================
== smartcastAndInitialization ==
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: * NEW: r(x) -> <v1>
x !is String <v2>: Boolean NEW: magic[IS](x !is String|<v1>) -> <v2>
{ y = 42 } <v3>: {<: () -> Unit} NEW: r({ y = 42 }) -> <v3>
callsAndInverts(x !is String) { y = 42 } <v4>: Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v2>, <v3>) -> <v4>
y <v5>: Int NEW: r(y) -> <v5>
println(y) <v6>: * NEW: call(println(y), println|<v5>) -> <v6>
DEBUG_INFO_SMARTCAST <v7>: * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v7>
!DEBUG_INFO_SMARTCAST <v8>: * NEW: call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v7>) -> <v8>
{ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } <v8>: * COPY
y <v9>: Int NEW: r(y) -> <v9>
println(y) <v10>: * NEW: call(println(y), println|<v9>) -> <v10>
x <v11>: * NEW: r(x) -> <v11>
x.< <v12>: * NEW: magic[UNSUPPORTED_ELEMENT](x.<|<v11>) -> <v12>
{ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v12>: * COPY
if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v13>: * NEW: merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v8>, <v12>) -> <v13>
y <v14>: Int NEW: r(y) -> <v14>
println(y) <v15>: * NEW: call(println(y), println|<v14>) -> <v15>
{ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) } <v15>: * COPY
=====================
== inlined anonymous_1 ==
{ y = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
y = 42 !<v1>: *
y = 42 !<v1>: * COPY
=====================
== inPresenceOfLazy ==
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
<v1>: Boolean NEW: magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> <v1>
unknownBoolean <v2>: Boolean NEW: r(unknownBoolean) -> <v2>
x <v3>: * NEW: r(x) -> <v3>
x !is String <v4>: Boolean NEW: magic[IS](x !is String|<v3>) -> <v4>
{ y = 42 } <v5>: {<: () -> Unit} NEW: r({ y = 42 }) -> <v5>
callsAndInverts(x !is String) { y = 42 } <v6>: Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v4>, <v5>) -> <v6>
unknownBoolean && callsAndInverts(x !is String) { y = 42 } <v7>: Boolean NEW: magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|<v2>, <v6>) -> <v7>
y <v8>: Int NEW: r(y) -> <v8>
println(y) <v9>: * NEW: call(println(y), println|<v8>) -> <v9>
DEBUG_INFO_SMARTCAST <v10>: * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v10>
!DEBUG_INFO_SMARTCAST <v11>: * NEW: call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v10>) -> <v11>
{ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } <v11>: * COPY
y <v12>: Int NEW: r(y) -> <v12>
println(y) <v13>: * NEW: call(println(y), println|<v12>) -> <v13>
x <v14>: * NEW: r(x) -> <v14>
x.< <v15>: * NEW: magic[UNSUPPORTED_ELEMENT](x.<|<v14>) -> <v15>
{ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v15>: * COPY
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v16>: * NEW: merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v11>, <v15>) -> <v16>
y <v17>: Int NEW: r(y) -> <v17>
println(y) <v18>: * NEW: call(println(y), println|<v17>) -> <v18>
{ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) } <v18>: * COPY
=====================
== inlined anonymous_2 ==
{ y = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
y = 42 !<v1>: *
y = 42 !<v1>: * COPY
=====================
@@ -0,0 +1,184 @@
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> Unit) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== unknownRun ==
inline fun <T> unknownRun(block: () -> T): T = block()
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
r(block) -> <v1> INIT: in: {} out: {}
mark(block())
call(block(), invoke|<v1>) -> <v2>
ret(*|<v2>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== throwIfNotCalled ==
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(<!UNINITIALIZED_VARIABLE!>x<!>) })
v(val x: Int) INIT: in: {} out: {x=D}
mark(outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) INIT: in: {x=D} out: {x=D}
mark({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> <v0>
mark(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
L3 [after inlined declaration]:
mark(println(<)
magic[UNRESOLVED_CALL](println(<|!<v2>) -> <v3>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
---------------------
L4:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException())
mark({ myRun { x = 42 return@outer } })
jmp?(L6)
d({ myRun { x = 42 return@outer } }) INIT: in: {} out: {} USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
L6 [after local declaration]:
r({ myRun { x = 42 return@outer } }) -> <v0> INIT: in: {x=D} out: {x=D}
mark(unknownRun { myRun { x = 42 return@outer } })
call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|<v0>) -> <v1>
mark(throw java.lang.IllegalArgumentException())
mark(java.lang.IllegalArgumentException())
mark(IllegalArgumentException())
call(IllegalArgumentException(), <init>) -> <v2>
throw (throw java.lang.IllegalArgumentException()|<v2>)
L5:
3 <END> INIT: in: {x=ID} out: {x=ID}
error:
<ERROR> INIT: in: {x=D} out: {x=D}
sink:
<SINK> INIT: in: {x=I?} out: {x=I?} USE: in: {} out: {}
=====================
== anonymous_2 ==
{
myRun {
x = 42
return@outer
}
}
---------------------
L7:
5 <START> INIT: in: {x=D} out: {x=D}
6 mark(myRun { x = 42 return@outer })
mark({ x = 42 return@outer })
r({ x = 42 return@outer }) -> <v0>
mark(myRun { x = 42 return@outer })
call(myRun { x = 42 return@outer }, myRun|<v0>) -> <v1>
L9 [before inlined declaration]:
inlined({ x = 42 return@outer }) USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
L8:
L10 [after inlined declaration]:
5 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_3 ==
{
x = 42
return@outer
}
---------------------
L11:
7 <START> INIT: in: {x=D} out: {x=D}
8 mark(x = 42 return@outer)
r(42) -> <v0> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ}
ret L5 INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
L12:
- 7 <END>
error:
- <ERROR>
sink:
- <SINK>
=====================
@@ -0,0 +1,26 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
inline fun <T> unknownRun(block: () -> T): T = block()
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
@@ -0,0 +1,96 @@
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: * NEW: call(block(), invoke|<v3>) -> <v4>
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } <v4>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== unknownRun ==
inline fun <T> unknownRun(block: () -> T): T = block()
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
block <v1>: {<: () -> T} NEW: r(block) -> <v1>
block() <v2>: {<: T} NEW: call(block(), invoke|<v1>) -> <v2>
=====================
== throwIfNotCalled ==
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
---------------------
{ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v0>: {<: () -> Unit} NEW: r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> <v0>
outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v0>: {<: () -> Unit} COPY
myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v1>: * NEW: call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
println !<v2>: *
println(< <v3>: * NEW: magic[UNRESOLVED_CALL](println(<|!<v2>) -> <v3>
{ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(<!UNINITIALIZED_VARIABLE!>x<!>) } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
---------------------
{ myRun { x = 42 return@outer } } <v0>: {<: () -> Unit} NEW: r({ myRun { x = 42 return@outer } }) -> <v0>
unknownRun { myRun { x = 42 return@outer } } <v1>: * NEW: call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|<v0>) -> <v1>
IllegalArgumentException() <v2>: {<: Throwable} NEW: call(IllegalArgumentException(), <init>) -> <v2>
java.lang.IllegalArgumentException() <v2>: {<: Throwable} COPY
throw java.lang.IllegalArgumentException() !<v3>: *
unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() !<v3>: * COPY
=====================
== anonymous_2 ==
{
myRun {
x = 42
return@outer
}
}
---------------------
{ x = 42 return@outer } <v0>: {<: () -> Unit} NEW: r({ x = 42 return@outer }) -> <v0>
myRun { x = 42 return@outer } <v1>: * NEW: call(myRun { x = 42 return@outer }, myRun|<v0>) -> <v1>
myRun { x = 42 return@outer } <v1>: * COPY
=====================
== inlined anonymous_3 ==
{
x = 42
return@outer
}
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
return@outer !<v1>: *
x = 42 return@outer !<v1>: * COPY
=====================
@@ -0,0 +1,366 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(42) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== tryCatchInlined ==
fun tryCatchInlined() {
val x: Int
myRun {
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// I?
x.inc()
}
}
// I?
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } // I? x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) INIT: in: {x=D} out: {x=D}
r({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) -> <v0>
mark(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } })
call(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) INIT: in: {x=I?D} out: {x=I?D}
L3 [after inlined declaration]:
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v2> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v2>) -> <v3>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// I?
x.inc()
}
}
---------------------
L4:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() })
mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() })
jmp?(L6) USE: in: {x=READ} out: {x=READ}
5 mark({ x = someComputation() x.inc() })
mark(someComputation())
call(someComputation(), someComputation) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc()) INIT: in: {x=ID} out: {x=ID}
r(x) -> <v1>
mark(inc())
call(inc(), inc|<v1>) -> <v2>
4 jmp?(L6)
jmp(L7)
L6 [onException]:
5 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v3>) INIT: in: {x=I?D} out: {x=I?D}
6 mark({ // I? x.inc() }) INIT: in: {x=I?D} out: {x=I?D}
mark(x.inc())
r(x) -> <v4>
mark(inc())
call(inc(), inc|<v4>) -> <v5>
5 jmp(L7)
L7 [afterCatches]:
4 merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }|<v2>, <v5>) -> <v6>
3 ret(*|<v6>) L5
L5:
<END> USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=I?D} out: {x=I?D} USE: in: {x=READ} out: {x=READ}
=====================
== possibleReassignmentInTryCatch ==
fun possibleReassignmentInTryCatch() {
val x: Int
myRun {
x = 42
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// Possible reassignment
x = 42
x.inc()
}
// Initialized
x.inc()
}
// Initialized
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } // Initialized x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) INIT: in: {x=D} out: {x=D}
r({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) -> <v0>
mark(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() })
call(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L3 [after inlined declaration]:
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v2> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v2>) -> <v3>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_2 ==
{
x = 42
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// Possible reassignment
x = 42
x.inc()
}
// Initialized
x.inc()
}
---------------------
L4:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc())
r(42) -> <v0>
w(x|<v0>) INIT: in: {x=D} out: {x=ID}
mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }) INIT: in: {x=ID} out: {x=ID}
jmp?(L6)
5 mark({ x = someComputation() x.inc() })
mark(someComputation())
call(someComputation(), someComputation) -> <v1> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v1>) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc())
r(x) -> <v2>
mark(inc())
call(inc(), inc|<v2>) -> <v3>
4 jmp?(L6)
jmp(L7) USE: in: {x=READ} out: {x=READ}
L6 [onException]:
5 v(e: java.lang.Exception) INIT: in: {x=ID} out: {x=ID}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4> INIT: in: {x=ID} out: {x=ID}
w(e|<v4>) INIT: in: {x=ID} out: {x=ID}
6 mark({ // Possible reassignment x = 42 x.inc() }) INIT: in: {x=ID} out: {x=ID}
r(42) -> <v5> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v5>) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc())
r(x) -> <v6>
mark(inc())
call(inc(), inc|<v6>) -> <v7>
5 jmp(L7)
L7 [afterCatches]:
4 merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }|<v3>, <v7>) -> <v8>
mark(x.inc())
r(x) -> <v9>
mark(inc())
call(inc(), inc|<v9>) -> <v10>
3 ret(*|<v10>) L5
L5:
<END> USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
== tryCatchOuter ==
fun tryCatchOuter() {
var x: Int
try {
myRun {
x = someComputation()
x.inc()
}
}
catch (e: java.lang.UnsupportedOperationException) {
myRun { x = 42 }
}
catch (e: java.lang.Exception) {
// do nothing
}
// I? because we can leave with last catch-clause which doesn't initialize x
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ var x: Int try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } // I? because we can leave with last catch-clause which doesn't initialize x x.inc() })
v(var x: Int) INIT: in: {} out: {x=D}
mark(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }) INIT: in: {x=D} out: {x=D}
jmp?(L2) USE: in: {x=READ} out: {x=READ}
3 mark({ myRun { x = someComputation() x.inc() } })
mark({ x = someComputation() x.inc() })
r({ x = someComputation() x.inc() }) -> <v0>
mark(myRun { x = someComputation() x.inc() })
call(myRun { x = someComputation() x.inc() }, myRun|<v0>) -> <v1>
L3 [before inlined declaration]:
inlined({ x = someComputation() x.inc() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L4 [after inlined declaration]:
2 jmp?(L2)
jmp(L7)
L2 [onException]:
jmp?(L8) INIT: in: {x=I?D} out: {x=I?D} USE: in: {x=READ} out: {x=READ}
3 v(e: java.lang.UnsupportedOperationException) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.UnsupportedOperationException) -> <v2> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v2>) INIT: in: {x=I?D} out: {x=I?D}
4 mark({ myRun { x = 42 } }) INIT: in: {x=I?D} out: {x=I?D}
mark({ x = 42 })
r({ x = 42 }) -> <v3>
mark(myRun { x = 42 })
call(myRun { x = 42 }, myRun|<v3>) -> <v4>
L9 [before inlined declaration]:
inlined({ x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L10 [after inlined declaration]:
3 jmp(L7)
L8 [catch 0]:
v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v5> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v5>) INIT: in: {x=I?D} out: {x=I?D}
4 mark({ // do nothing }) INIT: in: {x=I?D} out: {x=I?D}
read (Unit)
3 jmp(L7)
L7 [afterCatches]:
2 merge(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }|<v1>, <v4>, !<v6>) -> <v7>
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v8> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v8>) -> <v9>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_3 ==
{
x = someComputation()
x.inc()
}
---------------------
L5:
4 <START> INIT: in: {x=D} out: {x=D}
5 mark(x = someComputation() x.inc())
mark(someComputation())
call(someComputation(), someComputation) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
mark(x.inc()) INIT: in: {x=ID} out: {x=ID}
r(x) -> <v1>
mark(inc())
call(inc(), inc|<v1>) -> <v2>
4 ret(*|<v2>) L6
L6:
<END> USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
== inlined anonymous_4 ==
{ x = 42 }
---------------------
L11:
5 <START> INIT: in: {x=I?D} out: {x=I?D}
6 mark(x = 42)
r(42) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L12:
5 <END> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
error:
- <ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,71 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun someComputation(): Int = 42
fun tryCatchInlined() {
val x: Int
myRun {
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// I?
x.inc()
}
}
// I?
x.inc()
}
fun possibleReassignmentInTryCatch() {
val x: Int
myRun {
x = 42
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// Possible reassignment
x = 42
x.inc()
}
// Initialized
x.inc()
}
// Initialized
x.inc()
}
fun tryCatchOuter() {
var x: Int
try {
myRun {
x = someComputation()
x.inc()
}
}
catch (e: java.lang.UnsupportedOperationException) {
myRun { x = 42 }
}
catch (e: java.lang.Exception) {
// do nothing
}
// I? because we can leave with last catch-clause which doesn't initialize x
x.inc()
}
@@ -0,0 +1,200 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
=====================
== tryCatchInlined ==
fun tryCatchInlined() {
val x: Int
myRun {
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// I?
x.inc()
}
}
// I?
x.inc()
}
---------------------
{ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } <v0>: {<: () -> Int} NEW: r({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) -> <v0>
myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } <v1>: * NEW: call(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ val x: Int myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } // I? x.inc() } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// I?
x.inc()
}
}
---------------------
<v3>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3>
someComputation() <v0>: Int NEW: call(someComputation(), someComputation) -> <v0>
x <v1>: Int NEW: r(x) -> <v1>
inc() <v2>: Int NEW: call(inc(), inc|<v1>) -> <v2>
x.inc() <v2>: Int COPY
{ x = someComputation() x.inc() } <v2>: Int COPY
x <v4>: Int NEW: r(x) -> <v4>
inc() <v5>: Int NEW: call(inc(), inc|<v4>) -> <v5>
x.inc() <v5>: Int COPY
{ // I? x.inc() } <v5>: Int COPY
try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } <v6>: Int NEW: merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }|<v2>, <v5>) -> <v6>
try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } <v6>: Int COPY
=====================
== possibleReassignmentInTryCatch ==
fun possibleReassignmentInTryCatch() {
val x: Int
myRun {
x = 42
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// Possible reassignment
x = 42
x.inc()
}
// Initialized
x.inc()
}
// Initialized
x.inc()
}
---------------------
{ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } <v0>: {<: () -> Int} NEW: r({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) -> <v0>
myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } <v1>: * NEW: call(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ val x: Int myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } // Initialized x.inc() } <v3>: * COPY
=====================
== inlined anonymous_2 ==
{
x = 42
try {
x = someComputation()
x.inc()
}
catch (e: java.lang.Exception) {
// Possible reassignment
x = 42
x.inc()
}
// Initialized
x.inc()
}
---------------------
<v4>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v4>
42 <v0>: Int NEW: r(42) -> <v0>
someComputation() <v1>: Int NEW: call(someComputation(), someComputation) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ x = someComputation() x.inc() } <v3>: * COPY
42 <v5>: Int NEW: r(42) -> <v5>
x <v6>: Int NEW: r(x) -> <v6>
inc() <v7>: * NEW: call(inc(), inc|<v6>) -> <v7>
x.inc() <v7>: * COPY
{ // Possible reassignment x = 42 x.inc() } <v7>: * COPY
try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } <v8>: * NEW: merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }|<v3>, <v7>) -> <v8>
x <v9>: Int NEW: r(x) -> <v9>
inc() <v10>: Int NEW: call(inc(), inc|<v9>) -> <v10>
x.inc() <v10>: Int COPY
x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() <v10>: Int COPY
=====================
== tryCatchOuter ==
fun tryCatchOuter() {
var x: Int
try {
myRun {
x = someComputation()
x.inc()
}
}
catch (e: java.lang.UnsupportedOperationException) {
myRun { x = 42 }
}
catch (e: java.lang.Exception) {
// do nothing
}
// I? because we can leave with last catch-clause which doesn't initialize x
x.inc()
}
---------------------
<v2>: {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: java.lang.UnsupportedOperationException) -> <v2>
<v5>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v5>
{ x = someComputation() x.inc() } <v0>: {<: () -> Int} NEW: r({ x = someComputation() x.inc() }) -> <v0>
myRun { x = someComputation() x.inc() } <v1>: * NEW: call(myRun { x = someComputation() x.inc() }, myRun|<v0>) -> <v1>
{ myRun { x = someComputation() x.inc() } } <v1>: * COPY
{ x = 42 } <v3>: {<: () -> Unit} NEW: r({ x = 42 }) -> <v3>
myRun { x = 42 } <v4>: * NEW: call(myRun { x = 42 }, myRun|<v3>) -> <v4>
{ myRun { x = 42 } } <v4>: * COPY
{ // do nothing } !<v6>: *
try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } <v7>: * NEW: merge(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }|<v1>, <v4>, !<v6>) -> <v7>
x <v8>: Int NEW: r(x) -> <v8>
inc() <v9>: * NEW: call(inc(), inc|<v8>) -> <v9>
x.inc() <v9>: * COPY
{ var x: Int try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } // I? because we can leave with last catch-clause which doesn't initialize x x.inc() } <v9>: * COPY
=====================
== inlined anonymous_3 ==
{
x = someComputation()
x.inc()
}
---------------------
someComputation() <v0>: Int NEW: call(someComputation(), someComputation) -> <v0>
x <v1>: Int NEW: r(x) -> <v1>
inc() <v2>: Int NEW: call(inc(), inc|<v1>) -> <v2>
x.inc() <v2>: Int COPY
x = someComputation() x.inc() <v2>: Int COPY
=====================
== inlined anonymous_4 ==
{ x = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
x = 42 !<v1>: *
x = 42 !<v1>: * COPY
=====================
@@ -0,0 +1,187 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(block: () -> T) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](block: () -> T) -> <v0> INIT: in: {} out: {}
w(block|<v0>) INIT: in: {} out: {}
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {}
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2)
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START> INIT: in: {} out: {}
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
L0:
1 <START> INIT: in: {} out: {}
r(42) -> <v0>
ret(*|<v0>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== report ==
fun report(x: Int) = Unit
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(x: Int) INIT: in: {} out: {}
magic[FAKE_INITIALIZER](x: Int) -> <v0> INIT: in: {} out: {}
w(x|<v0>) INIT: in: {} out: {}
r(Unit) -> <v1> INIT: in: {} out: {}
ret(*|<v1>) L1
L1:
<END>
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== innerTryCatchFinally ==
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() })
v(val x: Int) INIT: in: {} out: {x=D}
mark({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) INIT: in: {x=D} out: {x=D}
r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> <v0>
mark(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } })
call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
L3 [after inlined declaration]:
mark(x.inc()) USE: in: {x=READ} out: {x=READ}
r(x) -> <v2> USE: in: {} out: {x=READ}
mark(inc())
call(inc(), inc|<v2>) -> <v3>
L1:
1 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
---------------------
L4:
3 <START> INIT: in: {x=D} out: {x=D}
4 mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 })
mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 })
jmp?(L6)
jmp?(L7)
5 mark({ x = someComputation() report(x) })
mark(someComputation())
call(someComputation(), someComputation) -> <v0> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v0>) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
r(x) -> <v1> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ}
mark(report(x))
call(report(x), report|<v1>) -> <v2>
4 jmp?(L6)
jmp?(L7)
jmp(L8)
L6 [onException]:
5 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D}
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3> INIT: in: {x=I?D} out: {x=I?D}
w(e|<v3>) INIT: in: {x=I?D} out: {x=I?D}
6 mark({ x = 42 report(x) }) INIT: in: {x=I?D} out: {x=I?D}
r(42) -> <v4> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v4>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
r(x) -> <v5> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ}
mark(report(x))
call(report(x), report|<v5>) -> <v6>
5 jmp(L8)
L8 [afterCatches]:
4 jmp(L9)
L7 [onExceptionToFinallyBlock]:
L10 [start finally]:
5 mark({ x = 0 }) INIT: in: {x=I?D} out: {x=I?D}
r(0) -> <v7> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v7>) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
L11 [finish finally]:
4 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ}
L9 [skipFinallyToErrorBlock]:
L12 [copy of L7, onExceptionToFinallyBlock]:
5 mark({ x = 0 })
r(0) -> <v7> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ}
w(x|<v7>) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ}
4 merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|<v2>, <v6>) -> <v9>
L5:
3 <END>
error:
<ERROR>
sink:
<SINK> USE: in: {x=READ} out: {x=READ}
=====================
@@ -0,0 +1,32 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun someComputation(): Int = 42
fun report(x: Int) = Unit
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
@@ -0,0 +1,93 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
=====================
== report ==
fun report(x: Int) = Unit
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](x: Int) -> <v0>
Unit <v1>: Unit NEW: r(Unit) -> <v1>
=====================
== innerTryCatchFinally ==
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
---------------------
{ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } <v0>: {<: () -> Unit} NEW: r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> <v0>
myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } <v1>: * NEW: call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
---------------------
<v3>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3>
someComputation() <v0>: Int NEW: call(someComputation(), someComputation) -> <v0>
x <v1>: Int NEW: r(x) -> <v1>
report(x) <v2>: * NEW: call(report(x), report|<v1>) -> <v2>
{ x = someComputation() report(x) } <v2>: * COPY
42 <v4>: Int NEW: r(42) -> <v4>
x <v5>: Int NEW: r(x) -> <v5>
report(x) <v6>: * NEW: call(report(x), report|<v5>) -> <v6>
{ x = 42 report(x) } <v6>: * COPY
0 <v7>: Int NEW: r(0) -> <v7>
x = 0 !<v8>: *
{ x = 0 } !<v8>: * COPY
try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } <v9>: * NEW: merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|<v2>, <v6>) -> <v9>
try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } <v9>: * COPY
=====================
@@ -0,0 +1,298 @@
== myLet ==
inline fun <T, R> T.myLet(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
---------------------
L0:
1 <START>
v(block: (T) -> R)
magic[FAKE_INITIALIZER](block: (T) -> R) -> <v0>
w(block|<v0>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
r(this, <this>) -> <v4>
mark(block(this))
call(block(this), invoke|<v3>, <v4>) -> <v5>
ret(*|<v5>) L1
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
L0:
1 <START>
v(block: () -> Unit)
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
w(block|<v0>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
=====================
== anonymous_1 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== unknownRun ==
inline fun unknownRun(block: () -> Unit) = block()
---------------------
L0:
1 <START>
v(block: () -> Unit)
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
w(block|<v0>)
r(block) -> <v1>
mark(block())
call(block(), invoke|<v1>) -> <v2>
ret(*|<v2>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
L0:
1 <START>
r(false) -> <v0>
ret(*|<v0>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== threeLayersReturn ==
fun threeLayersReturn(x: Int?): Int? {
// Inner always jumps to outer
// And middle always calls inner
// So, in fact, middle never finished normally
// Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization
// Hence, outer doesn't performs definite initialization
val y: Int
myRun outer@ {
myRun middle@ {
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
// Possible to report unreachable here
y = 54
}
return y.inc()
}
---------------------
L0:
1 <START>
v(x: Int?)
magic[FAKE_INITIALIZER](x: Int?) -> <v0>
w(x|<v0>)
2 mark({ // Inner always jumps to outer // And middle always calls inner // So, in fact, middle never finished normally // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization // Hence, outer doesn't performs definite initialization val y: Int myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } return y.inc() })
v(val y: Int)
mark(outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 })
mark({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 })
r({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) -> <v1>
mark(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 })
call(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }, myRun|<v1>) -> <v2>
L2 [before inlined declaration]:
inlined({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 })
L3 [after inlined declaration]:
mark(y.inc())
r(y) -> <v3>
mark(inc())
call(inc(), inc|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_2 ==
{
myRun middle@ {
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
// Possible to report unreachable here
y = 54
}
---------------------
L4:
3 <START>
4 mark(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54)
mark(middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } })
mark({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } })
r({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) -> <v0>
mark(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } })
call(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }, myRun|<v0>) -> <v1>
L6 [before inlined declaration]:
inlined({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) NEXT:[<SINK>]
L7 [after inlined declaration]:
- r(54) -> <v2> PREV:[]
- w(y|<v2>) PREV:[]
L5:
3 <END> NEXT:[<SINK>] PREV:[ret(*|<v3>) L5, ret(*|<v5>) L5]
error:
- <ERROR> PREV:[]
sink:
<SINK> PREV:[<END>, inlined({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } })]
=====================
== inlined anonymous_3 ==
{
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
---------------------
L8:
5 <START>
6 mark(x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } })
mark(x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } })
r(x) -> <v0>
mark(inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } })
mark({ if (it == null) { return@outer Unit } else { return@outer Unit } })
r({ if (it == null) { return@outer Unit } else { return@outer Unit } }) -> <v1>
mark(myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } })
call(myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }, myLet|<v0>, <v1>)
L10 [before inlined declaration]:
inlined({ if (it == null) { return@outer Unit } else { return@outer Unit } }) NEXT:[<SINK>]
L11 [after inlined declaration]:
- jmp(error) NEXT:[<ERROR>] PREV:[]
- jmp(error) NEXT:[<ERROR>] PREV:[]
L9:
- 5 <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
<SINK> PREV:[inlined({ if (it == null) { return@outer Unit } else { return@outer Unit } })]
=====================
== inlined anonymous_4 ==
{
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
---------------------
L12:
7 <START>
8 mark(if (it == null) { return@outer Unit } else { return@outer Unit })
mark(if (it == null) { return@outer Unit } else { return@outer Unit })
r(it) -> <v0>
r(null) -> <v1>
mark(it == null)
call(it == null, equals|<v0>, <v1>) -> <v2>
jf(L14|<v2>) NEXT:[mark({ return@outer Unit }), mark({ return@outer Unit })]
9 mark({ return@outer Unit })
r(Unit) -> <v3>
ret(*|<v3>) L5 NEXT:[<END>]
- 8 jmp(L15) NEXT:[merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!<v4>, !<v6>) -> <v7>] PREV:[]
L14 [else branch]:
9 mark({ return@outer Unit }) PREV:[jf(L14|<v2>)]
r(Unit) -> <v5>
ret(*|<v5>) L5 NEXT:[<END>]
L15 ['if' expression result]:
- 8 merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!<v4>, !<v6>) -> <v7> PREV:[]
- 7 ret(*|<v7>) L13 PREV:[]
L13:
- <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -0,0 +1,45 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T, R> T.myLet(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
inline fun unknownRun(block: () -> Unit) = block()
fun getBool(): Boolean = false
fun threeLayersReturn(x: Int?): Int? {
// Inner always jumps to outer
// And middle always calls inner
// So, in fact, middle never finished normally
// Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization
// Hence, outer doesn't performs definite initialization
val y: Int
myRun outer@ {
myRun middle@ {
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
// Possible to report unreachable here
y = 54
}
return y.inc()
}
@@ -0,0 +1,168 @@
== myLet ==
inline fun <T, R> T.myLet(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
---------------------
<v0>: {<: (T) -> R} NEW: magic[FAKE_INITIALIZER](block: (T) -> R) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: (T) -> R} NEW: r(block) -> <v3>
this <v4>: {<: T} COPY
this <v4>: {<: T} NEW: r(this, <this>) -> <v4>
block(this) <v5>: {<: R} NEW: call(block(this), invoke|<v3>, <v4>) -> <v5>
return block(this) !<v6>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) } !<v6>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<R>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: * NEW: call(block(), invoke|<v3>) -> <v4>
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } <v4>: * COPY
=====================
== anonymous_1 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== unknownRun ==
inline fun unknownRun(block: () -> Unit) = block()
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
block <v1>: {<: () -> Unit} NEW: r(block) -> <v1>
block() <v2>: Unit NEW: call(block(), invoke|<v1>) -> <v2>
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
false <v0>: Boolean NEW: r(false) -> <v0>
=====================
== threeLayersReturn ==
fun threeLayersReturn(x: Int?): Int? {
// Inner always jumps to outer
// And middle always calls inner
// So, in fact, middle never finished normally
// Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization
// Hence, outer doesn't performs definite initialization
val y: Int
myRun outer@ {
myRun middle@ {
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
// Possible to report unreachable here
y = 54
}
return y.inc()
}
---------------------
<v0>: {<: Int?} NEW: magic[FAKE_INITIALIZER](x: Int?) -> <v0>
{ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } <v1>: {<: () -> Unit} NEW: r({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) -> <v1>
outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } <v1>: {<: () -> Unit} COPY
myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } <v2>: * NEW: call(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }, myRun|<v1>) -> <v2>
y <v3>: Int NEW: r(y) -> <v3>
inc() <v4>: {<: Int?} NEW: call(inc(), inc|<v3>) -> <v4>
y.inc() <v4>: {<: Int?} COPY
return y.inc() !<v5>: *
{ // Inner always jumps to outer // And middle always calls inner // So, in fact, middle never finished normally // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization // Hence, outer doesn't performs definite initialization val y: Int myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } return y.inc() } !<v5>: * COPY
=====================
== inlined anonymous_2 ==
{
myRun middle@ {
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
// Possible to report unreachable here
y = 54
}
---------------------
{ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } <v0>: {<: () -> Unit} NEW: r({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) -> <v0>
middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } <v0>: {<: () -> Unit} COPY
myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } <v1>: * NEW: call(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }, myRun|<v0>) -> <v1>
54 <v2>: Int NEW: r(54) -> <v2>
y = 54 !<v3>: *
myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 !<v3>: * COPY
=====================
== inlined anonymous_3 ==
{
x.myLet inner@ {
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
}
---------------------
x <v0>: {<: Int?} NEW: r(x) -> <v0>
{ if (it == null) { return@outer Unit } else { return@outer Unit } } <v1>: {<: (Int?) -> Nothing} NEW: r({ if (it == null) { return@outer Unit } else { return@outer Unit } }) -> <v1>
inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } <v1>: {<: (Int?) -> Nothing} COPY
myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !<v2>: *
x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !<v2>: * COPY
x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !<v2>: * COPY
=====================
== inlined anonymous_4 ==
{
if (it == null) {
return@outer Unit
}
else {
return@outer Unit
}
}
---------------------
it <v0>: * NEW: r(it) -> <v0>
null <v1>: * NEW: r(null) -> <v1>
it == null <v2>: Boolean NEW: call(it == null, equals|<v0>, <v1>) -> <v2>
Unit <v3>: Unit NEW: r(Unit) -> <v3>
return@outer Unit !<v4>: *
{ return@outer Unit } !<v4>: * COPY
Unit <v5>: Unit NEW: r(Unit) -> <v5>
return@outer Unit !<v6>: *
{ return@outer Unit } !<v6>: * COPY
if (it == null) { return@outer Unit } else { return@outer Unit } <v7>: Nothing NEW: merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!<v4>, !<v6>) -> <v7>
if (it == null) { return@outer Unit } else { return@outer Unit } <v7>: Nothing COPY
=====================
@@ -0,0 +1,148 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START>
v(block: () -> Unit)
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
w(block|<v0>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
L0:
1 <START>
r(false) -> <v0>
ret(*|<v0>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== withLabeledReturn ==
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
---------------------
L0:
1 <START>
v(y: Int)
magic[FAKE_INITIALIZER](y: Int) -> <v0>
w(y|<v0>)
2 mark({ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) })
v(val x = myRun outer@ { myRun { return@outer Unit } println(y) })
mark(outer@ { myRun { return@outer Unit } println(y) })
mark({ myRun { return@outer Unit } println(y) })
r({ myRun { return@outer Unit } println(y) }) -> <v1>
mark(myRun outer@ { myRun { return@outer Unit } println(y) })
call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|<v1>) -> <v2>
L2 [before inlined declaration]:
inlined({ myRun { return@outer Unit } println(y) })
L3 [after inlined declaration]:
w(x|<v2>)
r(y) -> <v3>
mark(println(y))
call(println(y), println|<v3>) -> <v4>
r(x) -> <v5>
mark(println(x))
call(println(x), println|<v5>) -> <v6>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_1 ==
{
myRun { return@outer Unit }
println(y)
}
---------------------
L4:
3 <START>
4 mark(myRun { return@outer Unit } println(y))
mark({ return@outer Unit })
r({ return@outer Unit }) -> <v0>
mark(myRun { return@outer Unit })
call(myRun { return@outer Unit }, myRun|<v0>) -> <v1>
L6 [before inlined declaration]:
inlined({ return@outer Unit }) NEXT:[<SINK>]
L7 [after inlined declaration]:
- r(y) -> <v2> PREV:[]
- mark(println(y)) PREV:[]
- call(println(y), println|<v2>) -> <v3> PREV:[]
L5:
3 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L5]
error:
- <ERROR> PREV:[]
sink:
<SINK> PREV:[<END>, inlined({ return@outer Unit })]
=====================
== inlined anonymous_2 ==
{ return@outer Unit }
---------------------
L8:
5 <START>
6 mark(return@outer Unit)
r(Unit) -> <v0>
ret(*|<v0>) L5 NEXT:[<END>]
L9:
- 5 <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -0,0 +1,22 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun getBool(): Boolean = false
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
@@ -0,0 +1,73 @@
== myRun ==
inline fun myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: Unit NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== getBool ==
fun getBool(): Boolean = false
---------------------
false <v0>: Boolean NEW: r(false) -> <v0>
=====================
== withLabeledReturn ==
fun withLabeledReturn(y: Int) {
val x = myRun outer@ {
myRun { return@outer Unit }
println(y)
}
println(y)
println(x)
}
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](y: Int) -> <v0>
{ myRun { return@outer Unit } println(y) } <v1>: {<: () -> Unit} NEW: r({ myRun { return@outer Unit } println(y) }) -> <v1>
outer@ { myRun { return@outer Unit } println(y) } <v1>: {<: () -> Unit} COPY
myRun outer@ { myRun { return@outer Unit } println(y) } <v2>: Unit NEW: call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|<v1>) -> <v2>
y <v3>: Int NEW: r(y) -> <v3>
println(y) <v4>: * NEW: call(println(y), println|<v3>) -> <v4>
x <v5>: * NEW: r(x) -> <v5>
println(x) <v6>: * NEW: call(println(x), println|<v5>) -> <v6>
{ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) } <v6>: * COPY
=====================
== inlined anonymous_1 ==
{
myRun { return@outer Unit }
println(y)
}
---------------------
{ return@outer Unit } <v0>: {<: () -> Unit} NEW: r({ return@outer Unit }) -> <v0>
myRun { return@outer Unit } <v1>: * NEW: call(myRun { return@outer Unit }, myRun|<v0>) -> <v1>
y <v2>: Int NEW: r(y) -> <v2>
println(y) <v3>: * NEW: call(println(y), println|<v2>) -> <v3>
myRun { return@outer Unit } println(y) <v3>: * COPY
=====================
== inlined anonymous_2 ==
{ return@outer Unit }
---------------------
Unit <v0>: Unit NEW: r(Unit) -> <v0>
return@outer Unit !<v1>: *
return@outer Unit !<v1>: * COPY
=====================
@@ -0,0 +1,243 @@
== callsAndInverts ==
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
---------------------
L0:
1 <START>
v(b: Boolean)
magic[FAKE_INITIALIZER](b: Boolean) -> <v0>
w(b|<v0>)
v(block: () -> Unit)
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v1>
w(block|<v1>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> <v2>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> <v2> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|<v2>) -> <v3>
r(block) -> <v4>
mark(block())
call(block(), invoke|<v4>) -> <v5>
r(b) -> <v6>
mark(!b)
call(!b, not|<v6>) -> <v7>
ret(*|<v7>) L1
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })]
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b)
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
magic[IMPLICIT_RECEIVER](returns(true)) -> <v4>
r(true) -> <v5>
mark(returns(true))
call(returns(true), returns|<v4>, <v5>) -> <v6>
mark((!b))
r(b) -> <v7>
mark(!b)
call(!b, not|<v7>) -> <v8>
mark(returns(true) implies (!b))
call(returns(true) implies (!b), implies|<v6>, <v8>) -> <v9>
magic[IMPLICIT_RECEIVER](returns(false)) -> <v10>
r(false) -> <v11>
mark(returns(false))
call(returns(false), returns|<v10>, <v11>) -> <v12>
r(b) -> <v13>
mark(returns(false) implies b)
call(returns(false) implies b, implies|<v12>, <v13>) -> <v14>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== smartcastAndInitialization ==
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
L0:
1 <START>
v(x: Any?)
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
2 mark({ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) })
v(val y: Int)
mark(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> })
mark(x !is String)
r(x) -> <v1>
magic[IS](x !is String|<v1>) -> <v2>
mark({ y = 42 })
r({ y = 42 }) -> <v3>
mark(callsAndInverts(x !is String) { y = 42 })
call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v2>, <v3>) -> <v4>
L2 [before inlined declaration]:
inlined({ y = 42 })
L3 [after inlined declaration]:
jf(L6|<v4>) NEXT:[mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }), mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })]
3 mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })
r(y) -> <v5>
mark(println(y))
call(println(y), println|<v5>) -> <v6>
magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v7>
mark(!DEBUG_INFO_SMARTCAST)
call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v7>) -> <v8>
2 jmp(L7) NEXT:[merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v8>, <v12>) -> <v13>]
L6 [else branch]:
3 mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }) PREV:[jf(L6|<v4>)]
r(y) -> <v9>
mark(println(y))
call(println(y), println|<v9>) -> <v10>
mark(x.<)
r(x) -> <v11>
magic[UNSUPPORTED_ELEMENT](x.<|<v11>) -> <v12>
L7 ['if' expression result]:
2 merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v8>, <v12>) -> <v13> PREV:[jmp(L7), magic[UNSUPPORTED_ELEMENT](x.<|<v11>) -> <v12>]
r(y) -> <v14>
mark(println(y))
call(println(y), println|<v14>) -> <v15>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_1 ==
{ y = 42 }
---------------------
L4:
3 <START>
4 mark(y = 42)
r(42) -> <v0>
w(y|<v0>)
L5:
3 <END> NEXT:[<SINK>]
error:
- <ERROR> PREV:[]
sink:
<SINK> PREV:[<END>]
=====================
== inPresenceOfLazy ==
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
L0:
1 <START>
v(x: Any?)
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
v(unknownBoolean: Boolean)
magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> <v1>
w(unknownBoolean|<v1>)
2 mark({ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) })
v(val y: Int)
mark(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> })
r(unknownBoolean) -> <v2>
jf(L2|<v2>) NEXT:[magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|<v2>, <v6>) -> <v7>, mark(x !is String)]
mark(x !is String)
r(x) -> <v3>
magic[IS](x !is String|<v3>) -> <v4>
mark({ y = 42 })
r({ y = 42 }) -> <v5>
mark(callsAndInverts(x !is String) { y = 42 })
call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v4>, <v5>) -> <v6>
L3 [before inlined declaration]:
inlined({ y = 42 })
L2 [result of boolean operation]:
L4 [after inlined declaration]:
magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|<v2>, <v6>) -> <v7> PREV:[jf(L2|<v2>), inlined({ y = 42 })]
jf(L7|<v7>) NEXT:[mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }), mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })]
3 mark({ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length })
r(y) -> <v8>
mark(println(y))
call(println(y), println|<v8>) -> <v9>
magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v10>
mark(!DEBUG_INFO_SMARTCAST)
call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v10>) -> <v11>
2 jmp(L8) NEXT:[merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v11>, <v15>) -> <v16>]
L7 [else branch]:
3 mark({ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }) PREV:[jf(L7|<v7>)]
r(y) -> <v12>
mark(println(y))
call(println(y), println|<v12>) -> <v13>
mark(x.<)
r(x) -> <v14>
magic[UNSUPPORTED_ELEMENT](x.<|<v14>) -> <v15>
L8 ['if' expression result]:
2 merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v11>, <v15>) -> <v16> PREV:[jmp(L8), magic[UNSUPPORTED_ELEMENT](x.<|<v14>) -> <v15>]
r(y) -> <v17>
mark(println(y))
call(println(y), println|<v17>) -> <v18>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_2 ==
{ y = 42 }
---------------------
L5:
3 <START>
4 mark(y = 42)
r(42) -> <v0>
w(y|<v0>)
L6:
3 <END> NEXT:[<SINK>]
error:
- <ERROR> PREV:[]
sink:
<SINK> PREV:[<END>]
=====================
@@ -0,0 +1,44 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
@@ -0,0 +1,136 @@
== callsAndInverts ==
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
block()
return !b
}
---------------------
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> <v0>
<v1>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v1>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } <v2>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> <v2>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } <v3>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|<v2>) -> <v3>
block <v4>: {<: () -> Unit} NEW: r(block) -> <v4>
block() <v5>: * NEW: call(block(), invoke|<v4>) -> <v5>
b <v6>: Boolean NEW: r(b) -> <v6>
!b <v7>: Boolean NEW: call(!b, not|<v6>) -> <v7>
return !b !<v8>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b } !<v8>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
returns(true) implies (!b)
returns(false) implies b
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
<v10>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(false)) -> <v10>
<v4>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(true)) -> <v4>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
true <v5>: * NEW: r(true) -> <v5>
returns(true) <v6>: {<: SimpleEffect} NEW: call(returns(true), returns|<v4>, <v5>) -> <v6>
b <v7>: Boolean NEW: r(b) -> <v7>
!b <v8>: Boolean NEW: call(!b, not|<v7>) -> <v8>
(!b) <v8>: Boolean COPY
returns(true) implies (!b) <v9>: * NEW: call(returns(true) implies (!b), implies|<v6>, <v8>) -> <v9>
false <v11>: * NEW: r(false) -> <v11>
returns(false) <v12>: {<: SimpleEffect} NEW: call(returns(false), returns|<v10>, <v11>) -> <v12>
b <v13>: Boolean NEW: r(b) -> <v13>
returns(false) implies b <v14>: * NEW: call(returns(false) implies b, implies|<v12>, <v13>) -> <v14>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b <v14>: * COPY
=====================
== smartcastAndInitialization ==
fun smartcastAndInitialization(x: Any?) {
val y: Int
if (callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: * NEW: r(x) -> <v1>
x !is String <v2>: Boolean NEW: magic[IS](x !is String|<v1>) -> <v2>
{ y = 42 } <v3>: {<: () -> Unit} NEW: r({ y = 42 }) -> <v3>
callsAndInverts(x !is String) { y = 42 } <v4>: Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v2>, <v3>) -> <v4>
y <v5>: Int NEW: r(y) -> <v5>
println(y) <v6>: * NEW: call(println(y), println|<v5>) -> <v6>
DEBUG_INFO_SMARTCAST <v7>: * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v7>
!DEBUG_INFO_SMARTCAST <v8>: * NEW: call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v7>) -> <v8>
{ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } <v8>: * COPY
y <v9>: Int NEW: r(y) -> <v9>
println(y) <v10>: * NEW: call(println(y), println|<v9>) -> <v10>
x <v11>: * NEW: r(x) -> <v11>
x.< <v12>: * NEW: magic[UNSUPPORTED_ELEMENT](x.<|<v11>) -> <v12>
{ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v12>: * COPY
if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v13>: * NEW: merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v8>, <v12>) -> <v13>
y <v14>: Int NEW: r(y) -> <v14>
println(y) <v15>: * NEW: call(println(y), println|<v14>) -> <v15>
{ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) } <v15>: * COPY
=====================
== inlined anonymous_1 ==
{ y = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
y = 42 !<v1>: *
y = 42 !<v1>: * COPY
=====================
== inPresenceOfLazy ==
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
val y: Int
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
println(y)
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
else {
println(y)
x.<!UNRESOLVED_REFERENCE!>length<!>
}
println(y)
}
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
<v1>: Boolean NEW: magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> <v1>
unknownBoolean <v2>: Boolean NEW: r(unknownBoolean) -> <v2>
x <v3>: * NEW: r(x) -> <v3>
x !is String <v4>: Boolean NEW: magic[IS](x !is String|<v3>) -> <v4>
{ y = 42 } <v5>: {<: () -> Unit} NEW: r({ y = 42 }) -> <v5>
callsAndInverts(x !is String) { y = 42 } <v6>: Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|<v4>, <v5>) -> <v6>
unknownBoolean && callsAndInverts(x !is String) { y = 42 } <v7>: Boolean NEW: magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|<v2>, <v6>) -> <v7>
y <v8>: Int NEW: r(y) -> <v8>
println(y) <v9>: * NEW: call(println(y), println|<v8>) -> <v9>
DEBUG_INFO_SMARTCAST <v10>: * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> <v10>
!DEBUG_INFO_SMARTCAST <v11>: * NEW: call(!DEBUG_INFO_SMARTCAST, <ERROR FUNCTION>|<v10>) -> <v11>
{ println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } <v11>: * COPY
y <v12>: Int NEW: r(y) -> <v12>
println(y) <v13>: * NEW: call(println(y), println|<v12>) -> <v13>
x <v14>: * NEW: r(x) -> <v14>
x.< <v15>: * NEW: magic[UNSUPPORTED_ELEMENT](x.<|<v14>) -> <v15>
{ println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v15>: * COPY
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } <v16>: * NEW: merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> }|<v11>, <v15>) -> <v16>
y <v17>: Int NEW: r(y) -> <v17>
println(y) <v18>: * NEW: call(println(y), println|<v17>) -> <v18>
{ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) <!DEBUG_INFO_SMARTCAST!>x<!>.length } else { println(y) x.<!UNRESOLVED_REFERENCE!>length<!> } println(y) } <v18>: * COPY
=====================
== inlined anonymous_2 ==
{ y = 42 }
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
y = 42 !<v1>: *
y = 42 !<v1>: * COPY
=====================
@@ -0,0 +1,184 @@
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
L0:
1 <START>
v(block: () -> Unit)
magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
w(block|<v0>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== unknownRun ==
inline fun <T> unknownRun(block: () -> T): T = block()
---------------------
L0:
1 <START>
v(block: () -> T)
magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
w(block|<v0>)
r(block) -> <v1>
mark(block())
call(block(), invoke|<v1>) -> <v2>
ret(*|<v2>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== throwIfNotCalled ==
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
---------------------
L0:
1 <START>
2 mark({ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(<!UNINITIALIZED_VARIABLE!>x<!>) })
v(val x: Int)
mark(outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
mark({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> <v0>
mark(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() })
L3 [after inlined declaration]:
mark(println(<)
magic[UNRESOLVED_CALL](println(<|!<v2>) -> <v3>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_1 ==
{
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
---------------------
L4:
3 <START>
4 mark(unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException())
mark({ myRun { x = 42 return@outer } })
jmp?(L6) NEXT:[r({ myRun { x = 42 return@outer } }) -> <v0>, d({ myRun { x = 42 return@outer } })]
d({ myRun { x = 42 return@outer } }) NEXT:[<SINK>]
L6 [after local declaration]:
r({ myRun { x = 42 return@outer } }) -> <v0> PREV:[jmp?(L6)]
mark(unknownRun { myRun { x = 42 return@outer } })
call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|<v0>) -> <v1>
mark(throw java.lang.IllegalArgumentException())
mark(java.lang.IllegalArgumentException())
mark(IllegalArgumentException())
call(IllegalArgumentException(), <init>) -> <v2>
throw (throw java.lang.IllegalArgumentException()|<v2>) NEXT:[<ERROR>]
L5:
3 <END> NEXT:[<SINK>] PREV:[ret L5]
error:
<ERROR> PREV:[throw (throw java.lang.IllegalArgumentException()|<v2>)]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ myRun { x = 42 return@outer } })]
=====================
== anonymous_2 ==
{
myRun {
x = 42
return@outer
}
}
---------------------
L7:
5 <START>
6 mark(myRun { x = 42 return@outer })
mark({ x = 42 return@outer })
r({ x = 42 return@outer }) -> <v0>
mark(myRun { x = 42 return@outer })
call(myRun { x = 42 return@outer }, myRun|<v0>) -> <v1>
L9 [before inlined declaration]:
inlined({ x = 42 return@outer }) NEXT:[<SINK>]
L8:
L10 [after inlined declaration]:
5 <END> NEXT:[<SINK>] PREV:[]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, inlined({ x = 42 return@outer })]
=====================
== inlined anonymous_3 ==
{
x = 42
return@outer
}
---------------------
L11:
7 <START>
8 mark(x = 42 return@outer)
r(42) -> <v0>
w(x|<v0>)
ret L5 NEXT:[<END>]
L12:
- 7 <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -0,0 +1,26 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
inline fun <T> unknownRun(block: () -> T): T = block()
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
@@ -0,0 +1,96 @@
== myRun ==
inline fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> Unit} NEW: r(block) -> <v3>
block() <v4>: * NEW: call(block(), invoke|<v3>) -> <v4>
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } <v4>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<Unit>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== unknownRun ==
inline fun <T> unknownRun(block: () -> T): T = block()
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
block <v1>: {<: () -> T} NEW: r(block) -> <v1>
block() <v2>: {<: T} NEW: call(block(), invoke|<v1>) -> <v2>
=====================
== throwIfNotCalled ==
fun throwIfNotCalled() {
val x: Int
myRun outer@ {
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
println(<!UNINITIALIZED_VARIABLE!>x<!>)
}
---------------------
{ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v0>: {<: () -> Unit} NEW: r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> <v0>
outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v0>: {<: () -> Unit} COPY
myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } <v1>: * NEW: call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|<v0>) -> <v1>
println !<v2>: *
println(< <v3>: * NEW: magic[UNRESOLVED_CALL](println(<|!<v2>) -> <v3>
{ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(<!UNINITIALIZED_VARIABLE!>x<!>) } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
unknownRun {
myRun {
x = 42
return@outer
}
}
throw java.lang.IllegalArgumentException()
}
---------------------
{ myRun { x = 42 return@outer } } <v0>: {<: () -> Unit} NEW: r({ myRun { x = 42 return@outer } }) -> <v0>
unknownRun { myRun { x = 42 return@outer } } <v1>: * NEW: call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|<v0>) -> <v1>
IllegalArgumentException() <v2>: {<: Throwable} NEW: call(IllegalArgumentException(), <init>) -> <v2>
java.lang.IllegalArgumentException() <v2>: {<: Throwable} COPY
throw java.lang.IllegalArgumentException() !<v3>: *
unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() !<v3>: * COPY
=====================
== anonymous_2 ==
{
myRun {
x = 42
return@outer
}
}
---------------------
{ x = 42 return@outer } <v0>: {<: () -> Unit} NEW: r({ x = 42 return@outer }) -> <v0>
myRun { x = 42 return@outer } <v1>: * NEW: call(myRun { x = 42 return@outer }, myRun|<v0>) -> <v1>
myRun { x = 42 return@outer } <v1>: * COPY
=====================
== inlined anonymous_3 ==
{
x = 42
return@outer
}
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
return@outer !<v1>: *
x = 42 return@outer !<v1>: * COPY
=====================
@@ -0,0 +1,187 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
L0:
1 <START>
v(block: () -> T)
magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
w(block|<v0>)
2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() })
mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1> PREV:[jmp?(L2)]
mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) })
call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
r(block) -> <v3>
mark(block())
call(block(), invoke|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })]
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
L3:
3 <START>
4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
r(block) -> <v1>
mark(InvocationKind.EXACTLY_ONCE)
r(EXACTLY_ONCE) -> <v2>
mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE))
call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
L4:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
L0:
1 <START>
r(42) -> <v0>
ret(*|<v0>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== report ==
fun report(x: Int) = Unit
---------------------
L0:
1 <START>
v(x: Int)
magic[FAKE_INITIALIZER](x: Int) -> <v0>
w(x|<v0>)
r(Unit) -> <v1>
ret(*|<v1>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== innerTryCatchFinally ==
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
---------------------
L0:
1 <START>
2 mark({ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() })
v(val x: Int)
mark({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } })
r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> <v0>
mark(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } })
call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|<v0>) -> <v1>
L2 [before inlined declaration]:
inlined({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } })
L3 [after inlined declaration]:
mark(x.inc())
r(x) -> <v2>
mark(inc())
call(inc(), inc|<v2>) -> <v3>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
---------------------
L4:
3 <START>
4 mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 })
mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 })
jmp?(L6) NEXT:[v(e: java.lang.Exception), jmp?(L7)]
jmp?(L7) NEXT:[mark({ x = 0 }), mark({ x = someComputation() report(x) })]
5 mark({ x = someComputation() report(x) })
mark(someComputation())
call(someComputation(), someComputation) -> <v0>
w(x|<v0>)
r(x) -> <v1>
mark(report(x))
call(report(x), report|<v1>) -> <v2>
4 jmp?(L6) NEXT:[v(e: java.lang.Exception), jmp?(L7)]
jmp?(L7) NEXT:[mark({ x = 0 }), jmp(L8)]
jmp(L8) NEXT:[jmp(L9)]
L6 [onException]:
5 v(e: java.lang.Exception) PREV:[jmp?(L6), jmp?(L6)]
magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3>
w(e|<v3>)
6 mark({ x = 42 report(x) })
r(42) -> <v4>
w(x|<v4>)
r(x) -> <v5>
mark(report(x))
call(report(x), report|<v5>) -> <v6>
5 jmp(L8)
L8 [afterCatches]:
4 jmp(L9) NEXT:[mark({ x = 0 })] PREV:[jmp(L8), jmp(L8)]
L7 [onExceptionToFinallyBlock]:
L10 [start finally]:
5 mark({ x = 0 }) PREV:[jmp?(L7), jmp?(L7)]
r(0) -> <v7>
w(x|<v7>)
L11 [finish finally]:
4 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]:
L12 [copy of L7, onExceptionToFinallyBlock]:
5 mark({ x = 0 }) PREV:[jmp(L9)]
r(0) -> <v7>
w(x|<v7>)
4 merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|<v2>, <v6>) -> <v9>
L5:
3 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[jmp(error)]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -0,0 +1,32 @@
// LANGUAGE_VERSION: 1.3
import kotlin.internal.contracts.*
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun someComputation(): Int = 42
fun report(x: Int) = Unit
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
@@ -0,0 +1,93 @@
== myRun ==
inline fun <T> myRun(block: () -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> <v0>
{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v1>: {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> <v1>
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <v2>: * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|<v1>) -> <v2>
block <v3>: {<: () -> T} NEW: r(block) -> <v3>
block() <v4>: {<: T} NEW: call(block(), invoke|<v3>) -> <v4>
return block() !<v5>: *
{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !<v5>: * COPY
=====================
== anonymous_0 ==
{
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
---------------------
<v0>: {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> <v0>
block <v1>: {<: Function<T>} NEW: r(block) -> <v1>
EXACTLY_ONCE <v2>: {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> <v2>
InvocationKind.EXACTLY_ONCE <v2>: {<: InvocationKind} COPY
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|<v0>, <v1>, <v2>) -> <v3>
callsInPlace(block, InvocationKind.EXACTLY_ONCE) <v3>: * COPY
=====================
== someComputation ==
fun someComputation(): Int = 42
---------------------
42 <v0>: Int NEW: r(42) -> <v0>
=====================
== report ==
fun report(x: Int) = Unit
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](x: Int) -> <v0>
Unit <v1>: Unit NEW: r(Unit) -> <v1>
=====================
== innerTryCatchFinally ==
fun innerTryCatchFinally() {
val x: Int
myRun {
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
x.inc()
}
---------------------
{ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } <v0>: {<: () -> Unit} NEW: r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> <v0>
myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } <v1>: * NEW: call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|<v0>) -> <v1>
x <v2>: Int NEW: r(x) -> <v2>
inc() <v3>: * NEW: call(inc(), inc|<v2>) -> <v3>
x.inc() <v3>: * COPY
{ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
try {
x = someComputation()
report(x)
} catch (e: java.lang.Exception) {
x = 42
report(x)
} finally {
x = 0
}
}
---------------------
<v3>: {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> <v3>
someComputation() <v0>: Int NEW: call(someComputation(), someComputation) -> <v0>
x <v1>: Int NEW: r(x) -> <v1>
report(x) <v2>: * NEW: call(report(x), report|<v1>) -> <v2>
{ x = someComputation() report(x) } <v2>: * COPY
42 <v4>: Int NEW: r(42) -> <v4>
x <v5>: Int NEW: r(x) -> <v5>
report(x) <v6>: * NEW: call(report(x), report|<v5>) -> <v6>
{ x = 42 report(x) } <v6>: * COPY
0 <v7>: Int NEW: r(0) -> <v7>
x = 0 !<v8>: *
{ x = 0 } !<v8>: * COPY
try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } <v9>: * NEW: merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|<v2>, <v6>) -> <v9>
try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } <v9>: * COPY
=====================
File diff suppressed because it is too large Load Diff
@@ -28,218 +28,299 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/cfg-variables")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class DataFlowTestGenerated extends AbstractDataFlowTest {
public void testAllFilesPresentInCfg_variables() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("compiler/testData/cfg-variables/basic")
@TestMetadata("compiler/testData/cfg-variables")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Basic extends AbstractDataFlowTest {
public void testAllFilesPresentInBasic() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
public static class Cfg_variables extends AbstractDataFlowTest {
public void testAllFilesPresentInCfg_variables() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("ExhaustiveInitialization.kt")
public void testExhaustiveInitialization() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/ExhaustiveInitialization.kt");
doTest(fileName);
@TestMetadata("compiler/testData/cfg-variables/basic")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Basic extends AbstractDataFlowTest {
public void testAllFilesPresentInBasic() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("ExhaustiveInitialization.kt")
public void testExhaustiveInitialization() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/ExhaustiveInitialization.kt");
doTest(fileName);
}
@TestMetadata("IfWithUninitialized.kt")
public void testIfWithUninitialized() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/IfWithUninitialized.kt");
doTest(fileName);
}
@TestMetadata("InitializedNotDeclared.kt")
public void testInitializedNotDeclared() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/InitializedNotDeclared.kt");
doTest(fileName);
}
@TestMetadata("UsageInFunctionLiteral.kt")
public void testUsageInFunctionLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.kt");
doTest(fileName);
}
@TestMetadata("UseUninitializedInLambda.kt")
public void testUseUninitializedInLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UseUninitializedInLambda.kt");
doTest(fileName);
}
@TestMetadata("VariablesInitialization.kt")
public void testVariablesInitialization() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesInitialization.kt");
doTest(fileName);
}
@TestMetadata("VariablesUsage.kt")
public void testVariablesUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesUsage.kt");
doTest(fileName);
}
}
@TestMetadata("IfWithUninitialized.kt")
public void testIfWithUninitialized() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/IfWithUninitialized.kt");
doTest(fileName);
@TestMetadata("compiler/testData/cfg-variables/bugs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Bugs extends AbstractDataFlowTest {
public void testAllFilesPresentInBugs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("doWhileAssignment.kt")
public void testDoWhileAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileAssignment.kt");
doTest(fileName);
}
@TestMetadata("doWhileNotDefined.kt")
public void testDoWhileNotDefined() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileNotDefined.kt");
doTest(fileName);
}
@TestMetadata("initializationInLocalClass.kt")
public void testInitializationInLocalClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/initializationInLocalClass.kt");
doTest(fileName);
}
@TestMetadata("kt10243.kt")
public void testKt10243() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt10243.kt");
doTest(fileName);
}
@TestMetadata("kt4764.kt")
public void testKt4764() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt4764.kt");
doTest(fileName);
}
@TestMetadata("kt5469.kt")
public void testKt5469() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt");
doTest(fileName);
}
@TestMetadata("kt9825.kt")
public void testKt9825() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt");
doTest(fileName);
}
@TestMetadata("localObjectInConstructor.kt")
public void testLocalObjectInConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/localObjectInConstructor.kt");
doTest(fileName);
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt");
doTest(fileName);
}
@TestMetadata("varInitializationInIf.kt")
public void testVarInitializationInIf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIf.kt");
doTest(fileName);
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.kt");
doTest(fileName);
}
}
@TestMetadata("InitializedNotDeclared.kt")
public void testInitializedNotDeclared() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/InitializedNotDeclared.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/cfg-variables/lexicalScopes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LexicalScopes extends AbstractDataFlowTest {
public void testAllFilesPresentInLexicalScopes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/lexicalScopes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("UsageInFunctionLiteral.kt")
public void testUsageInFunctionLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.kt");
doTest(fileName);
}
@TestMetadata("doWhileScope.kt")
public void testDoWhileScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/doWhileScope.kt");
doTest(fileName);
}
@TestMetadata("UseUninitializedInLambda.kt")
public void testUseUninitializedInLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UseUninitializedInLambda.kt");
doTest(fileName);
}
@TestMetadata("forScope.kt")
public void testForScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/forScope.kt");
doTest(fileName);
}
@TestMetadata("VariablesInitialization.kt")
public void testVariablesInitialization() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesInitialization.kt");
doTest(fileName);
}
@TestMetadata("functionLiteralScope.kt")
public void testFunctionLiteralScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.kt");
doTest(fileName);
}
@TestMetadata("VariablesUsage.kt")
public void testVariablesUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesUsage.kt");
doTest(fileName);
@TestMetadata("ifScope.kt")
public void testIfScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/ifScope.kt");
doTest(fileName);
}
@TestMetadata("localClass.kt")
public void testLocalClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localClass.kt");
doTest(fileName);
}
@TestMetadata("localFunctionScope.kt")
public void testLocalFunctionScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.kt");
doTest(fileName);
}
@TestMetadata("localFunctionScopeWithoutBody.kt")
public void testLocalFunctionScopeWithoutBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.kt");
doTest(fileName);
}
@TestMetadata("localObject.kt")
public void testLocalObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localObject.kt");
doTest(fileName);
}
@TestMetadata("objectLiteralScope.kt")
public void testObjectLiteralScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.kt");
doTest(fileName);
}
@TestMetadata("propertyAccessorScope.kt")
public void testPropertyAccessorScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.kt");
doTest(fileName);
}
@TestMetadata("tryScope.kt")
public void testTryScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/tryScope.kt");
doTest(fileName);
}
@TestMetadata("whileScope.kt")
public void testWhileScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/whileScope.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/cfg-variables/bugs")
@TestMetadata("compiler/testData/cfgVariablesWithStdLib")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Bugs extends AbstractDataFlowTest {
public void testAllFilesPresentInBugs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
public static class CfgVariablesWithStdLib extends AbstractDataFlowTest {
public void testAllFilesPresentInCfgVariablesWithStdLib() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("doWhileAssignment.kt")
public void testDoWhileAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileAssignment.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/cfgVariablesWithStdLib/contracts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Contracts extends AbstractDataFlowTest {
public void testAllFilesPresentInContracts() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("doWhileNotDefined.kt")
public void testDoWhileNotDefined() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileNotDefined.kt");
doTest(fileName);
}
@TestMetadata("breakContinuesInInlinedLambda.kt")
public void testBreakContinuesInInlinedLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("initializationInLocalClass.kt")
public void testInitializationInLocalClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/initializationInLocalClass.kt");
doTest(fileName);
}
@TestMetadata("inlinedLambdaAlwaysThrows.kt")
public void testInlinedLambdaAlwaysThrows() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("kt10243.kt")
public void testKt10243() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt10243.kt");
doTest(fileName);
}
@TestMetadata("irrelevantUnknownClosure.kt")
public void testIrrelevantUnknownClosure() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("kt4764.kt")
public void testKt4764() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt4764.kt");
doTest(fileName);
}
@TestMetadata("nestedTryCatchFinally.kt")
public void testNestedTryCatchFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("kt5469.kt")
public void testKt5469() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt");
doTest(fileName);
}
@TestMetadata("nestedTryCatchs.kt")
public void testNestedTryCatchs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("kt9825.kt")
public void testKt9825() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt");
doTest(fileName);
}
@TestMetadata("nonReturningInlinedLambda.kt")
public void testNonReturningInlinedLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("localObjectInConstructor.kt")
public void testLocalObjectInConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/localObjectInConstructor.kt");
doTest(fileName);
}
@TestMetadata("returnsAndCalls.kt")
public void testReturnsAndCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt");
doTest(fileName);
}
@TestMetadata("throwIfNotCalled.kt")
public void testThrowIfNotCalled() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("varInitializationInIf.kt")
public void testVarInitializationInIf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIf.kt");
doTest(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/cfg-variables/lexicalScopes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LexicalScopes extends AbstractDataFlowTest {
public void testAllFilesPresentInLexicalScopes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/lexicalScopes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("doWhileScope.kt")
public void testDoWhileScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/doWhileScope.kt");
doTest(fileName);
}
@TestMetadata("forScope.kt")
public void testForScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/forScope.kt");
doTest(fileName);
}
@TestMetadata("functionLiteralScope.kt")
public void testFunctionLiteralScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.kt");
doTest(fileName);
}
@TestMetadata("ifScope.kt")
public void testIfScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/ifScope.kt");
doTest(fileName);
}
@TestMetadata("localClass.kt")
public void testLocalClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localClass.kt");
doTest(fileName);
}
@TestMetadata("localFunctionScope.kt")
public void testLocalFunctionScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.kt");
doTest(fileName);
}
@TestMetadata("localFunctionScopeWithoutBody.kt")
public void testLocalFunctionScopeWithoutBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.kt");
doTest(fileName);
}
@TestMetadata("localObject.kt")
public void testLocalObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localObject.kt");
doTest(fileName);
}
@TestMetadata("objectLiteralScope.kt")
public void testObjectLiteralScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.kt");
doTest(fileName);
}
@TestMetadata("propertyAccessorScope.kt")
public void testPropertyAccessorScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.kt");
doTest(fileName);
}
@TestMetadata("tryScope.kt")
public void testTryScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/tryScope.kt");
doTest(fileName);
}
@TestMetadata("whileScope.kt")
public void testWhileScope() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/whileScope.kt");
doTest(fileName);
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt");
doTestWithStdLib(fileName);
}
}
}
}
@@ -804,6 +804,54 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
}
}
@TestMetadata("compiler/testData/cfgWithStdLib")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CfgWithStdLib extends AbstractPseudoValueTest {
public void testAllFilesPresentInCfgWithStdLib() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("compiler/testData/cfgWithStdLib/contracts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Contracts extends AbstractPseudoValueTest {
public void testAllFilesPresentInContracts() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("labeledReturns.kt")
public void testLabeledReturns() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("nonReturningInlinedLambda.kt")
public void testNonReturningInlinedLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("returnsAndCalls.kt")
public void testReturnsAndCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("throwIfNotCalled.kt")
public void testThrowIfNotCalled() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt");
doTestWithStdLib(fileName);
}
}
}
@TestMetadata("compiler/testData/cfg-variables")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1019,4 +1067,82 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
}
}
}
@TestMetadata("compiler/testData/cfgVariablesWithStdLib")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CfgVariablesWithStdLib extends AbstractPseudoValueTest {
public void testAllFilesPresentInCfgVariablesWithStdLib() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("compiler/testData/cfgVariablesWithStdLib/contracts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Contracts extends AbstractPseudoValueTest {
public void testAllFilesPresentInContracts() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("breakContinuesInInlinedLambda.kt")
public void testBreakContinuesInInlinedLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("inlinedLambdaAlwaysThrows.kt")
public void testInlinedLambdaAlwaysThrows() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("irrelevantUnknownClosure.kt")
public void testIrrelevantUnknownClosure() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("nestedTryCatchFinally.kt")
public void testNestedTryCatchFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("nestedTryCatchs.kt")
public void testNestedTryCatchs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("nonReturningInlinedLambda.kt")
public void testNonReturningInlinedLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("returnsAndCalls.kt")
public void testReturnsAndCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("throwIfNotCalled.kt")
public void testThrowIfNotCalled() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt");
doTestWithStdLib(fileName);
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt");
doTestWithStdLib(fileName);
}
}
}
}