diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 745c1787f5ed..0ba4baff45a2 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.tpe <:< defn.NothingType) tree // For example 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..87cfdd764218 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -401,4 +401,53 @@ class TestBCode extends DottyBytecodeTest { } } + @Test def returnThrowInPatternMatch = { + val source = + """class Test { + | def test(a: Any): Int = { + | a match { + | case _: Test => ??? + | } + | } + |} + """.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(11)), + VarOp(Opcodes.ALOAD, 2), + TypeOp(Opcodes.CHECKCAST, "Test"), + VarOp(Opcodes.ASTORE, 3), + Field(Opcodes.GETSTATIC, "scala/Predef$", "MODULE$", "Lscala/Predef$;"), + Invoke(Opcodes.INVOKEVIRTUAL, "scala/Predef$", "$qmark$qmark$qmark", "()Lscala/runtime/Nothing$;", false), + Op(Opcodes.ATHROW), + Label(11), + 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(18), + FrameEntry(0, List(), List("java/lang/Throwable")), + Op(Opcodes.ATHROW), + Label(21), + FrameEntry(4, List(), List("java/lang/Throwable")), + Op(Opcodes.ATHROW) + ) + assert(instructions == expected, + "`test` was not properly generated\n" + diffInstructions(instructions, expected)) + + } + } + }