Skip to content

Commit eda6b0c

Browse files
Merge pull request #5082 from dotty-staging/small-pattern-match-optimization
Do not generate Return nodes for throw expressions
2 parents e02c785 + 2873a73 commit eda6b0c

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,8 @@ object PatternMatcher {
839839
default
840840
}
841841
case ResultPlan(tree) =>
842-
Return(tree, ref(resultLabel))
842+
if (tree.tpe <:< defn.NothingType) tree // For example MatchError
843+
else Return(tree, ref(resultLabel))
843844
}
844845
}
845846

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,4 +401,53 @@ class TestBCode extends DottyBytecodeTest {
401401
}
402402
}
403403

404+
@Test def returnThrowInPatternMatch = {
405+
val source =
406+
"""class Test {
407+
| def test(a: Any): Int = {
408+
| a match {
409+
| case _: Test => ???
410+
| }
411+
| }
412+
|}
413+
""".stripMargin
414+
415+
checkBCode(source) { dir =>
416+
val moduleIn = dir.lookupName("Test.class", directory = false)
417+
val moduleNode = loadClassNode(moduleIn.input)
418+
val method = getMethod(moduleNode, "test")
419+
420+
val instructions = instructionsFromMethod(method)
421+
val expected = List(
422+
VarOp(Opcodes.ALOAD, 1),
423+
VarOp(Opcodes.ASTORE, 2),
424+
VarOp(Opcodes.ALOAD, 2),
425+
TypeOp(Opcodes.INSTANCEOF, "Test"),
426+
Jump(Opcodes.IFEQ, Label(11)),
427+
VarOp(Opcodes.ALOAD, 2),
428+
TypeOp(Opcodes.CHECKCAST, "Test"),
429+
VarOp(Opcodes.ASTORE, 3),
430+
Field(Opcodes.GETSTATIC, "scala/Predef$", "MODULE$", "Lscala/Predef$;"),
431+
Invoke(Opcodes.INVOKEVIRTUAL, "scala/Predef$", "$qmark$qmark$qmark", "()Lscala/runtime/Nothing$;", false),
432+
Op(Opcodes.ATHROW),
433+
Label(11),
434+
FrameEntry(1, List("java/lang/Object"), List()),
435+
TypeOp(Opcodes.NEW, "scala/MatchError"),
436+
Op(Opcodes.DUP),
437+
VarOp(Opcodes.ALOAD, 2),
438+
Invoke(Opcodes.INVOKESPECIAL, "scala/MatchError", "<init>", "(Ljava/lang/Object;)V", false),
439+
Op(Opcodes.ATHROW),
440+
Label(18),
441+
FrameEntry(0, List(), List("java/lang/Throwable")),
442+
Op(Opcodes.ATHROW),
443+
Label(21),
444+
FrameEntry(4, List(), List("java/lang/Throwable")),
445+
Op(Opcodes.ATHROW)
446+
)
447+
assert(instructions == expected,
448+
"`test` was not properly generated\n" + diffInstructions(instructions, expected))
449+
450+
}
451+
}
452+
404453
}

0 commit comments

Comments
 (0)