Skip to content

Commit f421797

Browse files
committed
Fix #4866: do not lift try with no catch block
Forward port of scala/scala#922
1 parent 82f954e commit f421797

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import util.Store
2020
* is lifted to
2121
*
2222
* { def liftedTree$n() = try body catch handler; liftedTree$n() }
23+
*
24+
* However, don't lift try's without catch expressions (try-finally).
25+
* Lifting is needed only for try-catch expressions that are evaluated in a context
26+
* where the stack might not be empty. `finally` does not attempt to continue evaluation
27+
* after an exception, so the fact that values on the stack are 'lost' does not matter
28+
* (copied from https://github.com/scala/scala/pull/922).
2329
*/
2430
class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
2531
import ast.tpd._
@@ -58,7 +64,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
5864
liftingCtx(false)
5965

6066
override def transformTry(tree: Try)(implicit ctx: Context): Tree =
61-
if (needLift) {
67+
if (needLift && tree.cases.nonEmpty) {
6268
ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}")
6369
val fn = ctx.newSymbol(
6470
ctx.owner, LiftedTreeName.fresh(), Synthetic | Method,

tests/run/t4866.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Foo #lifted: 0
2+
FooLifted #lifted: 1

tests/run/t4866.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Test that try-finally aren't lifted, but try-catch are.
2+
3+
class Foo(param: => Object) {
4+
val field = try param finally ()
5+
}
6+
7+
class FooLifted(param: => Object) {
8+
val field = try param catch { case e: Exception => () } finally ()
9+
}
10+
11+
object Test extends App {
12+
def numLifted(o: Object): Int = {
13+
var lifted = 0
14+
15+
for (f <- o.getClass.getDeclaredMethods) {
16+
f.setAccessible(true)
17+
if (f.getName.startsWith("lifted")) {
18+
lifted += 1
19+
}
20+
}
21+
22+
lifted
23+
}
24+
25+
println("Foo #lifted: %d".format(numLifted(new Foo(new Object))))
26+
println("FooLifted #lifted: %d".format(numLifted(new FooLifted(new Object))))
27+
}

0 commit comments

Comments
 (0)