From 5241b37ad92c66ae5462eb0d2710e9d13da96b0b Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Mon, 23 Jul 2018 14:57:14 +0300 Subject: [PATCH] Fix fallthrough in suspendable switch [#KT-22694, #KT-23687] * do not explicitly put break for each case * add test for related cases --- .../box/coroutines/controlFlow/kt22694.kt | 49 +++++++++++++++++++ .../controlFlow/whenWithSuspensions.kt | 49 +++++++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 20 ++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 20 ++++++++ .../LightAnalysisModeTestGenerated.java | 20 ++++++++ .../js/coroutine/CoroutineBodyTransformer.kt | 2 - .../IrJsCodegenBoxTestGenerated.java | 10 ++++ .../semantics/JsCodegenBoxTestGenerated.java | 20 ++++++++ 8 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt create mode 100644 compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt b/compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt new file mode 100644 index 00000000000..e24d37ed9a3 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt @@ -0,0 +1,49 @@ +// IGNORE_BACKEND: JS_IR +// IGNORE_BACKEND: JVM_IR +// WITH_RUNTIME +// WITH_COROUTINES +// COMMON_COROUTINES_TEST +import helpers.* +import COROUTINES_PACKAGE.* +import COROUTINES_PACKAGE.intrinsics.* + +enum class Foo(vararg expected: String) { + A("start", "A", "end"), + B("start", "BCD", "end"), + C("start", "BCD", "end"), + D("start", "BCD", "end"), + E("start", "E", "end"), + F("start", "end"); + + val expected = expected.toList() +} + +fun box(): String { + for (c in Foo.values()) { + val actual = getSequence(c).toList() + if (actual != c.expected) { + return "FAIL: -- ${c.expected} != $actual" + } + } + + return "OK" +} + +fun getSequence(a: Foo) = + buildSequence { + yield("start") + when (a) { + Foo.A -> { + yield("A") + } + Foo.B, + Foo.C, + Foo.D-> { + yield("BCD") + } + Foo.E-> { + yield("E") + } + } + yield("end") + } \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt b/compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt new file mode 100644 index 00000000000..1e8c05f20f8 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt @@ -0,0 +1,49 @@ +// IGNORE_BACKEND: JS_IR +// IGNORE_BACKEND: JVM_IR +// WITH_RUNTIME +// WITH_COROUTINES +// COMMON_COROUTINES_TEST +import helpers.* +import COROUTINES_PACKAGE.* +import COROUTINES_PACKAGE.intrinsics.* + +var result = "" + +fun id(s: String) { result += s } + +suspend fun bar() = Unit + +suspend fun foo(a: Int) { + when (a) { + 0 -> { + id("0") + bar() // slice switch + } + 1, 2 -> { + id("$a") + } + else -> Unit + } +} + +fun builder(callback: suspend () -> Unit) { + callback.startCoroutine(object : ContinuationAdapter() { + override val context: CoroutineContext = EmptyCoroutineContext + override fun resume(value: Unit) = Unit + override fun resumeWithException(exception: Throwable) { + id("FAIL WITH EXCEPTION: ${exception.message}") + } + }) +} + +fun box():String { + id("a") + builder { + foo(0) + foo(1) + foo(2) + } + id("b") + if (result != "a012b") return "FAIL: $result" + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d457b424aad..15cfe4456b6 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -6130,6 +6130,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt", "kotlin.coroutines"); } + @TestMetadata("kt22694.kt") + public void testKt22694_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("kt22694.kt") + public void testKt22694_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines"); + } + @TestMetadata("labeledWhile.kt") public void testLabeledWhile_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/labeledWhile.kt", "kotlin.coroutines.experimental"); @@ -6180,6 +6190,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt", "kotlin.coroutines"); } + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines"); + } + @TestMetadata("whileStatement.kt") public void testWhileStatement_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index fc53f72bbb7..50097da3d44 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6130,6 +6130,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt", "kotlin.coroutines"); } + @TestMetadata("kt22694.kt") + public void testKt22694_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("kt22694.kt") + public void testKt22694_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines"); + } + @TestMetadata("labeledWhile.kt") public void testLabeledWhile_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/labeledWhile.kt", "kotlin.coroutines.experimental"); @@ -6180,6 +6190,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt", "kotlin.coroutines"); } + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines"); + } + @TestMetadata("whileStatement.kt") public void testWhileStatement_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index ef281933de2..ca2759dd778 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6130,6 +6130,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt", "kotlin.coroutines"); } + @TestMetadata("kt22694.kt") + public void testKt22694_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("kt22694.kt") + public void testKt22694_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines"); + } + @TestMetadata("labeledWhile.kt") public void testLabeledWhile_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/labeledWhile.kt", "kotlin.coroutines.experimental"); @@ -6180,6 +6190,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt", "kotlin.coroutines"); } + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines"); + } + @TestMetadata("whileStatement.kt") public void testWhileStatement_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt", "kotlin.coroutines.experimental"); diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt index d6fbda517b3..a758109636b 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt @@ -98,8 +98,6 @@ class CoroutineBodyTransformer(private val context: CoroutineTransformationConte currentBlock = caseBlock jsCase.statements.forEach { accept(it) } - currentBlock.statements += stateAndJump(jointBlock, x) - jsCase.statements.clear() jsCase.statements += caseBlock.statements } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index f3a0f5db315..2cbd7783cd0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -5410,6 +5410,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt", "kotlin.coroutines.experimental"); } + @TestMetadata("kt22694.kt") + public void testKt22694_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines.experimental"); + } + @TestMetadata("labeledWhile.kt") public void testLabeledWhile_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/labeledWhile.kt", "kotlin.coroutines.experimental"); @@ -5435,6 +5440,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt", "kotlin.coroutines.experimental"); } + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines.experimental"); + } + @TestMetadata("whileStatement.kt") public void testWhileStatement_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt", "kotlin.coroutines.experimental"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9cd5507af13..d33a6284cf4 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -5855,6 +5855,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt", "kotlin.coroutines"); } + @TestMetadata("kt22694.kt") + public void testKt22694_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("kt22694.kt") + public void testKt22694_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/kt22694.kt", "kotlin.coroutines"); + } + @TestMetadata("labeledWhile.kt") public void testLabeledWhile_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/labeledWhile.kt", "kotlin.coroutines.experimental"); @@ -5905,6 +5915,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt", "kotlin.coroutines"); } + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("whenWithSuspensions.kt") + public void testWhenWithSuspensions_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whenWithSuspensions.kt", "kotlin.coroutines"); + } + @TestMetadata("whileStatement.kt") public void testWhileStatement_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt", "kotlin.coroutines.experimental");