From f88c09b2c9069e95b3c1d9c7b6b67a0146aba5c3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 5 Sep 2018 15:21:01 +0200 Subject: [PATCH] Do not generate Return nodes for throw expressions Namely throw MatchError --- .../tools/dotc/transform/PatternMatcher.scala | 3 +- .../backend/jvm/DottyBytecodeTests.scala | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 745c1787f5ed..379bd9f9b1be 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -839,7 +839,8 @@ object PatternMatcher { default } case ResultPlan(tree) => - Return(tree, ref(resultLabel)) + if (tree.symbol eq defn.throwMethod) tree // Namely MatchError + else Return(tree, ref(resultLabel)) } } diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index fc76948490df..795847f608da 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -401,4 +401,49 @@ class TestBCode extends DottyBytecodeTest { } } + @Test def returnThrowInPatternMatch = { + val source = + """class Test { + | def test(a: Any): Int = { + | a match { + | case _: Test => 1 + | } + | } + |} + """.stripMargin + + checkBCode(source) { dir => + val moduleIn = dir.lookupName("Test.class", directory = false) + val moduleNode = loadClassNode(moduleIn.input) + val method = getMethod(moduleNode, "test") + + val instructions = instructionsFromMethod(method) + val expected = List( + VarOp(Opcodes.ALOAD, 1), + VarOp(Opcodes.ASTORE, 2), + VarOp(Opcodes.ALOAD, 2), + TypeOp(Opcodes.INSTANCEOF, "Test"), + Jump(Opcodes.IFEQ, Label(10)), + VarOp(Opcodes.ALOAD, 2), + TypeOp(Opcodes.CHECKCAST, "Test"), + VarOp(Opcodes.ASTORE, 3), + Op(Opcodes.ICONST_1), + Jump(Opcodes.GOTO, Label(17)), + Label(10), + FrameEntry(1, List("java/lang/Object"), List()), + TypeOp(Opcodes.NEW, "scala/MatchError"), + Op(Opcodes.DUP), + VarOp(Opcodes.ALOAD, 2), + Invoke(Opcodes.INVOKESPECIAL, "scala/MatchError", "", "(Ljava/lang/Object;)V", false), + Op(Opcodes.ATHROW), + Label(17), + FrameEntry(0, List("Test", "java/lang/Object", "java/lang/Object", "Test"), List(1)), + Op(Opcodes.IRETURN) + ) + assert(instructions == expected, + "`test` was not properly generated\n" + diffInstructions(instructions, expected)) + + } + } + }