File tree Expand file tree Collapse file tree 4 files changed +41
-1
lines changed
compiler/src/dotty/tools/dotc/transform Expand file tree Collapse file tree 4 files changed +41
-1
lines changed Original file line number Diff line number Diff line change @@ -20,6 +20,12 @@ import util.Store
20
20
* is lifted to
21
21
*
22
22
* { 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).
23
29
*/
24
30
class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
25
31
import ast .tpd ._
@@ -58,7 +64,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
58
64
liftingCtx(false )
59
65
60
66
override def transformTry (tree : Try )(implicit ctx : Context ): Tree =
61
- if (needLift) {
67
+ if (needLift && tree.cases.nonEmpty ) {
62
68
ctx.debuglog(i " lifting tree at ${tree.pos}, current owner = ${ctx.owner}" )
63
69
val fn = ctx.newSymbol(
64
70
ctx.owner, LiftedTreeName .fresh(), Synthetic | Method ,
Original file line number Diff line number Diff line change @@ -12,6 +12,9 @@ class LazyNullable(a: => Int) {
12
12
13
13
private [this ] val d = " D"
14
14
lazy val l3 = d + d // null out d (Scalac require single use?)
15
+
16
+ private [this ] val e = " E"
17
+ lazy val l4 = try e finally () // null out e
15
18
}
16
19
17
20
object LazyNullable2 {
@@ -47,6 +50,10 @@ class LazyNotNullable {
47
50
class Inner {
48
51
lazy val l8 = h
49
52
}
53
+
54
+ private [this ] val i = " I"
55
+ // not nullable because try is lifted, so i is used outside lazy val initializer
56
+ lazy val l9 = try i catch { case e : Exception => () }
50
57
}
51
58
52
59
trait LazyTrait {
@@ -87,6 +94,9 @@ object Test {
87
94
assert(lz.l3 == " DD" )
88
95
assertNull(" d" )
89
96
97
+ assert(lz.l4 == " E" )
98
+ assertNull(" e" )
99
+
90
100
assert(LazyNullable2 .l0 == " A" )
91
101
assert(readField(" a" , LazyNullable2 ) == null )
92
102
}
@@ -124,6 +134,9 @@ object Test {
124
134
assert(inner.l8 == " H" )
125
135
assertNotNull(" LazyNotNullable$$h" ) // fragile: test will break if compiler generated names change
126
136
137
+ assert(lz.l9 == " I" )
138
+ assertNotNull(" i" )
139
+
127
140
val fromTrait = new LazyTrait {}
128
141
assert(fromTrait.l0 == " A" )
129
142
assert(readField(" LazyTrait$$a" , fromTrait) != null ) // fragile: test will break if compiler generated names change
Original file line number Diff line number Diff line change
1
+ Foo #lifted: 0
2
+ FooLifted #lifted: 1
Original file line number Diff line number Diff line change
1
+ // Test that try-finally aren't lifted, but try-catch are.
2
+
3
+ class Foo {
4
+ val field = try 1 finally ()
5
+ }
6
+
7
+ class FooLifted {
8
+ val field = try 1 catch { case e : Exception => () } finally ()
9
+ }
10
+
11
+ object Test extends App {
12
+ def numLifted (o : Object ) = {
13
+ def isLifted (m : java.lang.reflect.Method ) = m.getName.startsWith(" lifted" )
14
+ o.getClass.getDeclaredMethods.count(isLifted)
15
+ }
16
+
17
+ println(" Foo #lifted: " + numLifted(new Foo ))
18
+ println(" FooLifted #lifted: " + numLifted(new FooLifted ))
19
+ }
You can’t perform that action at this time.
0 commit comments