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