diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 2802bae99fb3..860afd11d3cc 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -9,7 +9,7 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer import dotty.tools.dotc.core.Flags._ -import dotty.tools.dotc.core.NameKinds.{LazyBitMapName, LazyLocalInitName, LazyLocalName} +import dotty.tools.dotc.core.NameKinds.{LazyBitMapName, LazyLocalInitName, LazyLocalName, ExpandedName} import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Types._ @@ -73,7 +73,18 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { else { val isField = sym.owner.isClass if (isField) - if (sym.isAllOf(SyntheticModule)) + if sym.isAllOf(SyntheticModule) + && sym.allOverriddenSymbols.isEmpty + && !sym.name.is(ExpandedName) then + // I am not sure what the conditions for this optimization should be. + // It was applied for all synthetic objects, but this is clearly false, as t704 demonstrates. + // It seems we have to at least exclude synthetic objects that derive from mixins. + // This is done by demanding that the object does not override anything. + // Figuring out whether a symbol implements a trait module is not so simple. + // For non-private trait members we can check whether there is an overridden symbol. + // For private trait members this does not work, since `ensureNotPrivate` in phase Mixins + // does change the name but does not update the owner's scope, so `allOverriddenSymbols` does + // not work in that case. However, we can check whether the name is an ExpandedName instead. transformSyntheticModule(tree) else if (sym.isThreadUnsafe || ctx.settings.scalajs.value) if (sym.is(Module) && !ctx.settings.scalajs.value) { diff --git a/tests/run/t704.check b/tests/run/t704.check new file mode 100644 index 000000000000..86aa34fce796 --- /dev/null +++ b/tests/run/t704.check @@ -0,0 +1,6 @@ +xxxx should appear twice +zzzz should appear twice +yyyy should appear twice +xxxx should appear twice +zzzz should appear twice +yyyy should appear twice diff --git a/tests/pos/t704.scala b/tests/run/t704.scala similarity index 66% rename from tests/pos/t704.scala rename to tests/run/t704.scala index aedd8c03afdc..cab6f4ca8b42 100644 --- a/tests/pos/t704.scala +++ b/tests/run/t704.scala @@ -2,6 +2,11 @@ trait D { private val x = "xxxx should appear twice" private object xxxx { Console.println(x) } def get_xxxx: AnyRef = xxxx + + private val z = "zzzz should appear twice" + private lazy val zzzz = new ZZZZ + class ZZZZ { Console.println(z) } + def get_zzzz: AnyRef = zzzz } trait E extends D { @@ -9,13 +14,15 @@ trait E extends D { val y = "yyyy should appear twice" object yyyy { val x1 = get_xxxx + val z1 = get_zzzz Console.println(y) } yyyy } } class C extends E {} -object Go extends D { +object Test extends D { + object E def main(args : Array[String]): Unit = { new C().f() new C().f()