Skip to content

Commit 0a39a8f

Browse files
committed
Be faithful to initialization semantics
1 parent f8abf7e commit 0a39a8f

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ class Semantic {
545545
errorBuffer ++= res2.errors
546546

547547
// parents
548-
tpl.parents.foreach {
548+
def initParent(parent: Tree) = parent match {
549549
case tree @ Block(stats, NewExpr(tref, New(tpt), ctor, argss)) =>
550550
eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
551551
argss.flatten.foreach { arg =>
@@ -568,6 +568,26 @@ class Semantic {
568568
superCall(tref, tref.classSymbol.primaryConstructor, ref)
569569
}
570570

571+
// see spec 5.1 about "Template Evaluation".
572+
// https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
573+
if !klass.is(Flags.Trait) then
574+
// 1. first init parent class recursively
575+
// 2. initialize traits according to linearization order
576+
val superParent = tpl.parents.head
577+
val superCls = superParent.tpe.classSymbol.asClass
578+
initParent(superParent)
579+
580+
val parents = tpl.parents.tail
581+
val mixins = klass.baseClasses.tail.takeWhile(_ != superCls)
582+
mixins.reverse.foreach { mixin =>
583+
parents.find(_.tpe.classSymbol == mixin) match
584+
case Some(parent) => initParent(parent)
585+
case None =>
586+
val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
587+
superCall(tref, tref.classSymbol.primaryConstructor, superParent)
588+
}
589+
590+
571591
// class body
572592
tpl.body.foreach {
573593
case vdef : ValDef =>
@@ -585,6 +605,11 @@ class Semantic {
585605

586606
// ----- Utility methods and extractors --------------------------------
587607

608+
def typeRefOf(tp: Type)(using Context): TypeRef = tp.dealias.typeConstructor match {
609+
case tref: TypeRef => tref
610+
case hklambda: HKTypeLambda => typeRefOf(hklambda.resType)
611+
}
612+
588613
object Call {
589614
def unapply(tree: Tree)(using Context): Option[(Tree, List[List[Tree]])] =
590615
tree match
@@ -601,11 +626,6 @@ class Semantic {
601626
}
602627

603628
object NewExpr {
604-
private def typeRefOf(tp: Type)(using Context): TypeRef = tp.dealias.typeConstructor match {
605-
case tref: TypeRef => tref
606-
case hklambda: HKTypeLambda => typeRefOf(hklambda.resType)
607-
}
608-
609629
def unapply(tree: Tree)(using Context): Option[(TypeRef, New, Symbol, List[List[Tree]])] =
610630
tree match
611631
case Call(fn @ Select(newTree: New, init), argss) if init == nme.CONSTRUCTOR =>

0 commit comments

Comments
 (0)