From 710e13de39e66cdfabb4b30944daaf1224c2d32b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 31 Dec 2017 16:14:56 +0100 Subject: [PATCH 1/2] Fix #3634: Lazily evaluate static module accessors We did not use lazy evaluation for static objects, because these are usually evauated lazily by the backend. But that does not hold if the static module is an (accessor) def instead of a val. --- .../src/dotty/tools/dotc/transform/LazyVals.scala | 7 +++++-- tests/run/i3634.scala | 11 +++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/run/i3634.scala diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 0f930b353e36..11f0211fbad1 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -36,7 +36,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { class OffsetInfo(var defs: List[Tree], var ord:Int) val appendOffsetDefs = mutable.Map.empty[Symbol, OffsetInfo] - override def phaseName: String = "LazyVals" + override def phaseName: String = "lazyVals" /** List of names of phases that should have finished processing of tree * before this phase starts processing same tree */ @@ -61,7 +61,10 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { def transformLazyVal(tree: ValOrDefDef)(implicit ctx: Context): Tree = { val sym = tree.symbol - if (!(sym is Flags.Lazy) || sym.owner.is(Flags.Trait) || (sym.isStatic && sym.is(Flags.Module))) tree + if (!(sym is Flags.Lazy) || + sym.owner.is(Flags.Trait) || + (sym.isStatic && sym.is(Flags.Module, butNot = Flags.Method))) + tree else { val isField = sym.owner.isClass if (isField) { diff --git a/tests/run/i3634.scala b/tests/run/i3634.scala new file mode 100644 index 000000000000..6889b371fa08 --- /dev/null +++ b/tests/run/i3634.scala @@ -0,0 +1,11 @@ +trait T { + case object Foo +} + +object Bar extends T + +object Test { + def main(args: Array[String]): Unit = { + assert(Bar.Foo == Bar.Foo) // false + } +} From 6d84f521edc111ed806c73ca19bb4cfe006e8866 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 31 Dec 2017 17:43:22 +0100 Subject: [PATCH 2/2] Address review comments --- compiler/src/dotty/tools/dotc/transform/LazyVals.scala | 4 ++-- tests/pending/run/implicits-numeric.scala | 7 +++++++ tests/run/{i3634.scala => i3624.scala} | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 tests/pending/run/implicits-numeric.scala rename tests/run/{i3634.scala => i3624.scala} (58%) diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 11f0211fbad1..77fc11d25ab0 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -62,8 +62,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { def transformLazyVal(tree: ValOrDefDef)(implicit ctx: Context): Tree = { val sym = tree.symbol if (!(sym is Flags.Lazy) || - sym.owner.is(Flags.Trait) || - (sym.isStatic && sym.is(Flags.Module, butNot = Flags.Method))) + sym.owner.is(Flags.Trait) || // val is accessor, lazy field will be implemented in subclass + (sym.isStatic && sym.is(Flags.Module, butNot = Flags.Method))) // static module vals are implemented in the JVM by lazy loading tree else { val isField = sym.owner.isClass diff --git a/tests/pending/run/implicits-numeric.scala b/tests/pending/run/implicits-numeric.scala new file mode 100644 index 000000000000..dfb0ff46082a --- /dev/null +++ b/tests/pending/run/implicits-numeric.scala @@ -0,0 +1,7 @@ +object Test extends App { + + implicit def _1: Long = 1L + implicit def _2: Int = 0 + + println(implicitly[AnyVal]) +} diff --git a/tests/run/i3634.scala b/tests/run/i3624.scala similarity index 58% rename from tests/run/i3634.scala rename to tests/run/i3624.scala index 6889b371fa08..b9d20d05a4b0 100644 --- a/tests/run/i3634.scala +++ b/tests/run/i3624.scala @@ -3,9 +3,11 @@ trait T { } object Bar extends T +object Baz extends T object Test { def main(args: Array[String]): Unit = { - assert(Bar.Foo == Bar.Foo) // false + assert(Bar.Foo eq Bar.Foo) + assert(Bar.Foo ne Baz.Foo) } }