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,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
=====================