@@ -135,12 +135,13 @@ class Objects {
135135 def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [Value ], source : Tree ): Contextual [Result ] =
136136 value.instantiate(klass, ctor, args, source) ++ errors
137137
138- def ensureAccess (klass : ClassSymbol , source : Tree ): Contextual [Result ] =
138+ def ensureAccess (klass : ClassSymbol , source : Tree ): Contextual [Result ] = log( " ensure access " + value.show, printer) {
139139 value match
140140 case obj : ObjectRef =>
141141 if obj.klass == klass then this
142142 else obj.access(source) ++ errors
143143 case _ => this
144+ }
144145 }
145146
146147 /** The state that threads through the interpreter */
@@ -233,7 +234,7 @@ class Objects {
233234 eval(rhs, addr, target.owner.asClass, cacheResult = true )
234235 else
235236 given Trace = trace1
236- val obj = if heap.contains (addr) then heap(addr) else Objekt (addr.klass, mutable. Map .empty, mutable. Map .empty )
237+ val obj = heap(addr)
237238 if obj.fields.contains(target) then
238239 Result (obj.fields(target), Nil )
239240 else if target.is(Flags .ParamAccessor ) then
@@ -658,7 +659,7 @@ class Objects {
658659 }
659660
660661 /** Resolve C.this that appear in `klass` */
661- def resolveThis (target : ClassSymbol , thisV : Value , klass : ClassSymbol , source : Tree , elideObjectAccess : Boolean = false ): Contextual [Result ] = log(" resolving " + target.show + " , this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf [Value ].show) {
662+ def resolveThis (target : ClassSymbol , thisV : Value , klass : ClassSymbol , source : Tree , elideObjectAccess : Boolean = false ): Contextual [Result ] = log(" resolving " + target.show + " , this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf [Result ].show) {
662663 if target == klass then Result (thisV, Nil )
663664 else if target.is(Flags .Package ) then Result (Bottom , Nil )
664665 else if target.isStaticObjectRef then
@@ -699,7 +700,8 @@ class Objects {
699700
700701 val paramsMap = tpl.constr.termParamss.flatten.map(vdef => vdef.name -> vdef.symbol).toMap
701702
702- def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree ): Unit =
703+ type Handler = (() => Unit ) => Unit
704+ def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree , handler : Handler ): Unit =
703705 val cls = tref.classSymbol.asClass
704706 // update outer for super class
705707 val res = outerValue(tref, thisV, klass, source)
@@ -708,53 +710,57 @@ class Objects {
708710
709711 // follow constructor
710712 if cls.hasSource then
711- use(trace.add(source)) {
712- val res2 = thisV.call(ctor, args, superType = NoType , source)
713- errorBuffer ++= res2.errors
713+ handler { () =>
714+ use(trace.add(source)) {
715+ val res2 = thisV.call(ctor, args, superType = NoType , source)
716+ errorBuffer ++= res2.errors
717+ }
714718 }
719+ else
720+ handler { () => () }
715721
716722 // parents
717- def initParent (parent : Tree ) = parent match {
723+ def initParent (parent : Tree , handler : Handler ) = parent match {
718724 case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
719725 eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
720726 val resArgs = evalArgs(argss.flatten, thisV, klass)
721727 val argsValues = resArgs.map(_.value)
722728 val argsErrors = resArgs.flatMap(_.errors)
723729
724730 errorBuffer ++= argsErrors
725- superCall(tref, ctor, argsValues, tree)
731+ superCall(tref, ctor, argsValues, tree, handler )
726732
727733 case tree @ NewExpr (tref, New (tpt), ctor, argss) => // extends A(args)
728734 val resArgs = evalArgs(argss.flatten, thisV, klass)
729735 val argsValues = resArgs.map(_.value)
730736 val argsErrors = resArgs.flatMap(_.errors)
731737
732738 errorBuffer ++= argsErrors
733- superCall(tref, ctor, argsValues, tree)
739+ superCall(tref, ctor, argsValues, tree, handler )
734740
735741 case _ => // extends A or extends A[T]
736742 val tref = typeRefOf(parent.tpe)
737- superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent)
743+ superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent, handler )
738744 }
739745
740746 // see spec 5.1 about "Template Evaluation".
741747 // https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
742748 if ! klass.is(Flags .Trait ) then
749+ // outers are set first
750+ val tasks = new mutable.ArrayBuffer [() => Unit ]
751+ val handler : Handler = task => tasks.append(task)
752+
743753 // 1. first init parent class recursively
744754 // 2. initialize traits according to linearization order
745755 val superParent = tpl.parents.head
746756 val superCls = superParent.tpe.classSymbol.asClass
747- initParent(superParent)
748-
749- // Access to the object possible after this point
750- if klass.isStaticOwner then
751- thisV.updateField(klass, thisV)
757+ initParent(superParent, handler)
752758
753759 val parents = tpl.parents.tail
754760 val mixins = klass.baseClasses.tail.takeWhile(_ != superCls)
755761 mixins.reverse.foreach { mixin =>
756762 parents.find(_.tpe.classSymbol == mixin) match
757- case Some (parent) => initParent(parent)
763+ case Some (parent) => initParent(parent, handler )
758764 case None =>
759765 // According to the language spec, if the mixin trait requires
760766 // arguments, then the class must provide arguments to it explicitly
@@ -765,9 +771,21 @@ class Objects {
765771 // term arguments to B. That can only be done in a concrete class.
766772 val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
767773 val ctor = tref.classSymbol.primaryConstructor
768- if ctor.exists then superCall(tref, ctor, Nil , superParent)
774+ if ctor.exists then superCall(tref, ctor, Nil , superParent, handler )
769775 }
770776
777+ // initialize super classes after outers are set
778+ // 1. first call super class constructor
779+ // 2. make the object accessible
780+ // 3. call mixin initializations
781+ tasks.head()
782+
783+ // Access to the object possible after this point
784+ if klass.isStaticOwner then
785+ thisV.updateField(klass, thisV)
786+
787+ tasks.tail.foreach(task => task())
788+
771789
772790 // class body
773791 tpl.body.foreach {
0 commit comments