diff --git a/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.instructions b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.instructions new file mode 100644 index 00000000000..2f320ab80e7 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.instructions @@ -0,0 +1,104 @@ +== myRun == +inline fun Any?.myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + 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) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== test == +fun test(): String { + val x: String? = null + + x?.myRun { + return "" + } +} +--------------------- +L0: + 1 + 2 mark({ val x: String? = null x?.myRun { return "" } }) + v(val x: String? = null) + r(null) -> + w(x|) + mark(x?.myRun { return "" }) + jf(L2) NEXT:[, r(x) -> ] + r(x) -> + mark({ return "" }) + r({ return "" }) -> + mark(myRun { return "" }) + call(myRun { return "" }, myRun|, ) -> +L3 [before inlined declaration]: + inlined({ return "" }) NEXT:[] +L1: +L2 [result of call]: +L4 [after inlined declaration]: + 1 NEXT:[] PREV:[jf(L2), ret(*|) L1] +error: + PREV:[] +sink: + PREV:[, , inlined({ return "" })] +===================== +== inlined anonymous_1 == +{ + return "" + } +--------------------- +L5: + 3 + 4 mark(return "") + mark("") + r("") -> + ret(*|) L1 NEXT:[] +L6: +- 3 NEXT:[] PREV:[] +error: +- PREV:[] +sink: +- PREV:[] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt new file mode 100644 index 00000000000..59072af9c77 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.kt @@ -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 "" + } +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.values b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.values new file mode 100644 index 00000000000..8ad9a867f47 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/safeCallAndInPlaceReturn.values @@ -0,0 +1,53 @@ +== myRun == +inline fun Any?.myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : Unit NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== test == +fun test(): String { + val x: String? = null + + x?.myRun { + return "" + } +} +--------------------- +null : {<: String?} NEW: r(null) -> +x : * NEW: r(x) -> +{ return "" } : {<: () -> Unit} NEW: r({ return "" }) -> +myRun { return "" } : * NEW: call(myRun { return "" }, myRun|, ) -> +x?.myRun { return "" } : * COPY +{ val x: String? = null x?.myRun { return "" } } : * COPY +===================== +== inlined anonymous_1 == +{ + return "" + } +--------------------- +"" : String NEW: r("") -> +return "" !: * +return "" !: * COPY +===================== diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.kt new file mode 100644 index 00000000000..9717c13da5e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.kt @@ -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 "" } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.txt new file mode 100644 index 00000000000..7efe90276dd --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/safeCallAndInPlaceReturn.txt @@ -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) + diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index 6a7373f7b33..59b5eef3796 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index a0f660ff72c..f392ecb38fa 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index e5379ed7826..0be80022dfe 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 23f22cc80a0..836e8c1930c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -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");