Add test on in-place lambda with return + safecall

Currently, diagnostics behavior is undesired. The next commit fixes it

^KT-28061 In Progress
This commit is contained in:
Dmitry Savvinov
2018-11-12 15:19:24 +03:00
parent b918786336
commit c9e87bf353
9 changed files with 218 additions and 0 deletions
@@ -0,0 +1,104 @@
== myRun ==
inline fun Any?.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>]
=====================
== test ==
fun test(): String {
val x: String? = null
x?.myRun {
return ""
}
}
---------------------
L0:
1 <START>
2 mark({ val x: String? = null x?.myRun { return "" } })
v(val x: String? = null)
r(null) -> <v0>
w(x|<v0>)
mark(x?.myRun { return "" })
jf(L2) NEXT:[<END>, r(x) -> <v1>]
r(x) -> <v1>
mark({ return "" })
r({ return "" }) -> <v2>
mark(myRun { return "" })
call(myRun { return "" }, myRun|<v1>, <v2>) -> <v3>
L3 [before inlined declaration]:
inlined({ return "" }) NEXT:[<SINK>]
L1:
L2 [result of call]:
L4 [after inlined declaration]:
1 <END> NEXT:[<SINK>] PREV:[jf(L2), ret(*|<v0>) L1]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, inlined({ return "" })]
=====================
== inlined anonymous_1 ==
{
return ""
}
---------------------
L5:
3 <START>
4 mark(return "")
mark("")
r("") -> <v0>
ret(*|<v0>) L1 NEXT:[<END>]
L6:
- 3 <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -0,0 +1,18 @@
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
import kotlin.contracts.*
inline fun Any?.myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun test(): String {
val x: String? = null
x?.myRun {
return ""
}
}
@@ -0,0 +1,53 @@
== myRun ==
inline fun Any?.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
=====================
== test ==
fun test(): String {
val x: String? = null
x?.myRun {
return ""
}
}
---------------------
null <v0>: {<: String?} NEW: r(null) -> <v0>
x <v1>: * NEW: r(x) -> <v1>
{ return "" } <v2>: {<: () -> Unit} NEW: r({ return "" }) -> <v2>
myRun { return "" } <v3>: * NEW: call(myRun { return "" }, myRun|<v1>, <v2>) -> <v3>
x?.myRun { return "" } <v3>: * COPY
{ val x: String? = null x?.myRun { return "" } } <v3>: * COPY
=====================
== inlined anonymous_1 ==
{
return ""
}
---------------------
"" <v0>: String NEW: r("") -> <v0>
return "" !<v1>: *
return "" !<v1>: * COPY
=====================
@@ -0,0 +1,17 @@
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
import kotlin.contracts.*
inline fun Any?.myRun(block: () -> Unit): Unit {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
fun test(): String {
val x: String? = null
x?.myRun { return "" }
}
@@ -0,0 +1,6 @@
package
public fun test(): kotlin.String
public inline fun kotlin.Any?.myRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, EXACTLY_ONCE)
@@ -817,6 +817,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
runTest("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt");
}
@TestMetadata("safeCallAndInPlaceReturn.kt")
public void testSafeCallAndInPlaceReturn() throws Exception {
runTest("compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt");
}
@TestMetadata("throwIfNotCalled.kt")
public void testThrowIfNotCalled() throws Exception {
runTest("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
@@ -817,6 +817,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
runTest("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt");
}
@TestMetadata("safeCallAndInPlaceReturn.kt")
public void testSafeCallAndInPlaceReturn() throws Exception {
runTest("compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt");
}
@TestMetadata("throwIfNotCalled.kt")
public void testThrowIfNotCalled() throws Exception {
runTest("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
@@ -971,6 +971,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt");
}
@TestMetadata("safeCallAndInPlaceReturn.kt")
public void testSafeCallAndInPlaceReturn() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.kt");
}
@TestMetadata("severalJumpOutsFromInlinedLambda.kt")
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt");
@@ -971,6 +971,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt");
}
@TestMetadata("safeCallAndInPlaceReturn.kt")
public void testSafeCallAndInPlaceReturn() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.kt");
}
@TestMetadata("severalJumpOutsFromInlinedLambda.kt")
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt");