Skip to content

Unintended mixin initializer for overriden lazy val #4559

Closed
@gsps

Description

@gsps

The Mixin phase currently emits initializer calls for lazy vals in mixed in traits, even if those fields were overridden:

trait A {
  lazy val x = { println("super[A].x()"); 123 }
}

class B extends A {
  override lazy val x = 456
}

object HelloWorld { def main(args: Array[String]): Unit = { new B() } }

results in output

super[A].x()

My ad-hoc fix is to check for override during the generation of those initializers, though I'm not sure that's the correct way to handle it:

diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
index 437a8a45af3..d10ccebb370 100644
--- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
@@ -213,8 +213,10 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
               cls.pos)
           EmptyTree
       }
+      def needsInit(getter: Symbol) =
+        getter.isGetter && !was(getter, Deferred) && !cls.info.decl(getter.name).symbol.is(Override)
 
-      for (getter <- mixin.info.decls.toList if getter.isGetter && !was(getter, Deferred)) yield {
+      for (getter <- mixin.info.decls.toList if needsInit(getter)) yield {
         val isScala2x = mixin.is(Scala2x)
         def default = Underscore(getter.info.resultType)
         def initial = transformFollowing(superRef(initializer(getter)).appliedToNone)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions