Skip to content

Commit 36740bf

Browse files
authored
Merge pull request #5799 from dotty-staging/fix-lazyvals-try
Fix #1462: Move LiftTry as late as possible
2 parents 818fdbc + 3cc6e21 commit 36740bf

File tree

5 files changed

+18
-13
lines changed

5 files changed

+18
-13
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class Compiler {
6262
new ExtensionMethods, // Expand methods of value classes with extension methods
6363
new ShortcutImplicits, // Allow implicit functions without creating closures
6464
new ByNameClosures, // Expand arguments to by-name parameters to closures
65-
new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods
6665
new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope
6766
new ClassOf, // Expand `Predef.classOf` calls.
6867
new RefChecks) :: // Various checks mostly related to abstract members and overriding
@@ -97,9 +96,10 @@ class Compiler {
9796
List(new Constructors, // Collect initialization code in primary constructors
9897
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
9998
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
100-
new Instrumentation, // Count closure allocations under -Yinstrument-closures
101-
new GetClass) :: // Rewrites getClass calls on primitive types.
102-
List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to their implementations
99+
new Instrumentation, // Count closure allocations under -Yinstrument-closures
100+
new GetClass, // Rewrites getClass calls on primitive types.
101+
new LiftTry) :: // Put try expressions that might execute on non-empty stacks into their own methods their implementations
102+
List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to
103103
new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
104104
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
105105
new ElimStaticThis) :: // Replace `this` references to static objects by global identifiers

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
2828
class OffsetInfo(var defs: List[Tree], var ord:Int)
2929
private[this] val appendOffsetDefs = mutable.Map.empty[Symbol, OffsetInfo]
3030

31-
override def phaseName: String = "lazyVals"
31+
override def phaseName: String = LazyVals.name
3232

3333
/** List of names of phases that should have finished processing of tree
3434
* before this phase starts processing same tree */
@@ -435,6 +435,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
435435
}
436436

437437
object LazyVals {
438+
val name: String = "lazyVals"
439+
438440
object lazyNme {
439441
import Names.TermName
440442
object RLazyVals {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ import util.Store
3030
class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
3131
import ast.tpd._
3232

33-
/** the following two members override abstract members in Transform */
3433
val phaseName: String = "liftTry"
3534

35+
// See tests/run/t2333.scala for an example where running after the group of LazyVals matters
36+
override def runsAfterGroupsOf: Set[String] = Set(LazyVals.name)
37+
3638
private var NeedLift: Store.Location[Boolean] = _
3739
private def needLift(implicit ctx: Context): Boolean = ctx.store(NeedLift)
3840

tests/run/i1692.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class LazyNullable(a: => Int) {
1515

1616
private [this] val e = "E"
1717
lazy val l4 = try e finally () // null out e
18+
19+
private[this] val i = "I"
20+
// null out i even though the try ends up lifted, because the LazyVals phase runs before the LiftTry phase
21+
lazy val l5 = try i catch { case e: Exception => () }
1822
}
1923

2024
object LazyNullable2 {
@@ -51,9 +55,6 @@ class LazyNotNullable {
5155
lazy val l8 = h
5256
}
5357

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 => () }
5758
}
5859

5960
trait LazyTrait {
@@ -97,6 +98,9 @@ object Test {
9798
assert(lz.l4 == "E")
9899
assertNull("e")
99100

101+
assert(lz.l5 == "I")
102+
assertNull("i")
103+
100104
assert(LazyNullable2.l0 == "A")
101105
assert(readField("a", LazyNullable2) == null)
102106
}
@@ -134,9 +138,6 @@ object Test {
134138
assert(inner.l8 == "H")
135139
assertNotNull("LazyNotNullable$$h") // fragile: test will break if compiler generated names change
136140

137-
assert(lz.l9 == "I")
138-
assertNotNull("i")
139-
140141
val fromTrait = new LazyTrait {}
141142
assert(fromTrait.l0 == "A")
142143
assert(readField("LazyTrait$$a", fromTrait) != null) // fragile: test will break if compiler generated names change

tests/pending/run/t2333.scala renamed to tests/run/t2333.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ class A {
1111
object Test {
1212
def main(a: Array[String]): Unit = {
1313
val a = new A
14-
a.whatever
14+
a.whatever()
1515
}
1616
}

0 commit comments

Comments
 (0)