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");
|
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")
|
@TestMetadata("throwIfNotCalled.kt")
|
||||||
public void testThrowIfNotCalled() throws Exception {
|
public void testThrowIfNotCalled() throws Exception {
|
||||||
runTest("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
|
runTest("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
|
||||||
|
|||||||
@@ -817,6 +817,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
|||||||
runTest("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt");
|
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")
|
@TestMetadata("throwIfNotCalled.kt")
|
||||||
public void testThrowIfNotCalled() throws Exception {
|
public void testThrowIfNotCalled() throws Exception {
|
||||||
runTest("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt");
|
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");
|
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")
|
@TestMetadata("severalJumpOutsFromInlinedLambda.kt")
|
||||||
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
|
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt");
|
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");
|
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")
|
@TestMetadata("severalJumpOutsFromInlinedLambda.kt")
|
||||||
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
|
public void testSeveralJumpOutsFromInlinedLambda() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user