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:
+104
@@ -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
|
||||
=====================
|
||||
+17
@@ -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 "" }
|
||||
}
|
||||
+6
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user