diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index a669dcb79843..eb4183167097 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -76,6 +76,8 @@ class TryCatchPatterns extends MiniPhase { (pre == NoPrefix || pre.widen.typeSymbol.isStatic) && // Does not require outer class check !tp.symbol.is(Flags.Trait) && // Traits not supported by JVM tp.derivesFrom(defn.ThrowableClass) + case tp: AppliedType => + isSimpleThrowable(tp.tycon) case _ => false } diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index d288e26f1950..9f90bedf2598 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -3,6 +3,8 @@ package dotty.tools.backend.jvm import org.junit.Assert._ import org.junit.Test +import scala.tools.asm.Opcodes + class TestBCode extends DottyBytecodeTest { import ASMConverters._ @Test def nullChecks = { @@ -213,4 +215,30 @@ class TestBCode extends DottyBytecodeTest { assert(!arrayWrapped, "Arrays should not be wrapped when passed to a Java varargs method\n") } } + + @Test def efficientTryCases = { + val source = + """ + |class Test { + | def test = + | try print("foo") + | catch { + | case _: scala.runtime.NonLocalReturnControl[_] => () + | } + |} + """.stripMargin + + checkBCode(source) { dir => + val moduleIn = dir.lookupName("Test.class", directory = false) + val moduleNode = loadClassNode(moduleIn.input) + val method = getMethod(moduleNode, "test") + + val hasInstanceof = instructionsFromMethod(method).exists { + case TypeOp(Opcodes.INSTANCEOF, _) => true + case _ => false + } + + assert(!hasInstanceof, "Try case should not issue INSTANCEOF opcode\n") + } + } }