@@ -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
@@ -704,7 +705,8 @@ class Objects {
704705
705706 val paramsMap = tpl.constr.termParamss.flatten.map(vdef => vdef.name -> vdef.symbol).toMap
706707
707- def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree ): Unit =
708+ type Handler = (() => Unit ) => Unit
709+ def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree , handler : Handler ): Unit =
708710 val cls = tref.classSymbol.asClass
709711 // update outer for super class
710712 val res = outerValue(tref, thisV, klass, source)
@@ -713,53 +715,57 @@ class Objects {
713715
714716 // follow constructor
715717 if cls.hasSource then
716- use(trace.add(source)) {
717- val res2 = thisV.call(ctor, args, superType = NoType , source)
718- errorBuffer ++= res2.errors
718+ handler { () =>
719+ use(trace.add(source)) {
720+ val res2 = thisV.call(ctor, args, superType = NoType , source)
721+ errorBuffer ++= res2.errors
722+ }
719723 }
724+ else
725+ handler { () => () }
720726
721727 // parents
722- def initParent (parent : Tree ) = parent match {
728+ def initParent (parent : Tree , handler : Handler ) = parent match {
723729 case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
724730 eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
725731 val resArgs = evalArgs(argss.flatten, thisV, klass)
726732 val argsValues = resArgs.map(_.value)
727733 val argsErrors = resArgs.flatMap(_.errors)
728734
729735 errorBuffer ++= argsErrors
730- superCall(tref, ctor, argsValues, tree)
736+ superCall(tref, ctor, argsValues, tree, handler )
731737
732738 case tree @ NewExpr (tref, New (tpt), ctor, argss) => // extends A(args)
733739 val resArgs = evalArgs(argss.flatten, thisV, klass)
734740 val argsValues = resArgs.map(_.value)
735741 val argsErrors = resArgs.flatMap(_.errors)
736742
737743 errorBuffer ++= argsErrors
738- superCall(tref, ctor, argsValues, tree)
744+ superCall(tref, ctor, argsValues, tree, handler )
739745
740746 case _ => // extends A or extends A[T]
741747 val tref = typeRefOf(parent.tpe)
742- superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent)
748+ superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent, handler )
743749 }
744750
745751 // see spec 5.1 about "Template Evaluation".
746752 // https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
747753 if ! klass.is(Flags .Trait ) then
754+ // outers are set first
755+ val tasks = new mutable.ArrayBuffer [() => Unit ]
756+ val handler : Handler = task => tasks.append(task)
757+
748758 // 1. first init parent class recursively
749759 // 2. initialize traits according to linearization order
750760 val superParent = tpl.parents.head
751761 val superCls = superParent.tpe.classSymbol.asClass
752- initParent(superParent)
753-
754- // Access to the object possible after this point
755- if klass.isStaticOwner then
756- thisV.updateField(klass, thisV)
762+ initParent(superParent, handler)
757763
758764 val parents = tpl.parents.tail
759765 val mixins = klass.baseClasses.tail.takeWhile(_ != superCls)
760766 mixins.reverse.foreach { mixin =>
761767 parents.find(_.tpe.classSymbol == mixin) match
762- case Some (parent) => initParent(parent)
768+ case Some (parent) => initParent(parent, handler )
763769 case None =>
764770 // According to the language spec, if the mixin trait requires
765771 // arguments, then the class must provide arguments to it explicitly
@@ -770,9 +776,21 @@ class Objects {
770776 // term arguments to B. That can only be done in a concrete class.
771777 val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
772778 val ctor = tref.classSymbol.primaryConstructor
773- if ctor.exists then superCall(tref, ctor, Nil , superParent)
779+ if ctor.exists then superCall(tref, ctor, Nil , superParent, handler )
774780 }
775781
782+ // initialize super classes after outers are set
783+ // 1. first call super class constructor
784+ // 2. make the object accessible
785+ // 3. call mixin initializations
786+ tasks.head()
787+
788+ // Access to the object possible after this point
789+ if klass.isStaticOwner then
790+ thisV.updateField(klass, thisV)
791+
792+ tasks.tail.foreach(task => task())
793+
776794
777795 // class body
778796 tpl.body.foreach {
0 commit comments