Effects: add cfg-tests on inlined lambdas
========== Introduction of Effect System: 15/18
This commit is contained in:
@@ -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
|
||||
=====================
|
||||
+148
@@ -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
|
||||
=====================
|
||||
Reference in New Issue
Block a user