@@ -55,6 +55,10 @@ object Semantic {
5555 */
5656 sealed abstract class Value {
5757 def show : String = this .toString()
58+
59+ def isHot = this == Hot
60+ def isCold = this == Cold
61+ def isWarm = this .isInstanceOf [Warm ]
5862 }
5963
6064 /** A transitively initialized object */
@@ -99,9 +103,7 @@ object Semantic {
99103 }
100104
101105 /** A reference to the object under initialization pointed by `this` */
102- case class ThisRef (klass : ClassSymbol )(using @ constructorOnly h : Heap ) extends Ref {
103- val outer = Hot
104-
106+ case class ThisRef (klass : ClassSymbol , outer : Value , ctor : Symbol , args : List [Value ])(using @ constructorOnly h : Heap ) extends Ref {
105107 ensureObjectExists()
106108 }
107109
@@ -447,7 +449,7 @@ object Semantic {
447449 def widenArgs : List [Value ] = values.map(_.widenArg).toList
448450
449451 extension (value : Value )
450- def select (field : Symbol , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" select " + field.show, printer, (_ : Result ).show) {
452+ def select (field : Symbol , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" select " + field.show + " , this = " + value , printer, (_ : Result ).show) {
451453 if promoted.isCurrentObjectPromoted then Result (Hot , Nil )
452454 else value match {
453455 case Hot =>
@@ -613,6 +615,8 @@ object Semantic {
613615 val warm = Warm (klass, outer, ctor, args2)
614616 val argInfos2 = args.zip(args2).map { (argInfo, v) => argInfo.copy(value = v) }
615617 val res = warm.callConstructor(ctor, argInfos2, source)
618+ val task = ThisRef (klass, outer, ctor, args2)
619+ this .addTask(task)
616620 Result (warm, res.errors)
617621
618622 case Cold =>
@@ -630,6 +634,8 @@ object Semantic {
630634 val argInfos2 = args.zip(argsWidened).map { (argInfo, v) => argInfo.copy(value = v) }
631635 val warm = Warm (klass, outer, ctor, argsWidened)
632636 val res = warm.callConstructor(ctor, argInfos2, source)
637+ val task = ThisRef (klass, outer, ctor, argsWidened)
638+ this .addTask(task)
633639 Result (warm, res.errors)
634640
635641 case Fun (body, thisV, klass, env) =>
@@ -827,19 +833,22 @@ object Semantic {
827833 cls == defn.ObjectClass
828834
829835// ----- Work list ---------------------------------------------------
830- type Task = ThisRef
836+ case class Task ( value : ThisRef )( val trace : Trace )
831837
832838 class WorkList private [Semantic ]() {
833839 private var pendingTasks : List [Task ] = Nil
840+ private var checkedTasks : Set [Task ] = Set .empty
834841
835842 def addTask (task : Task ): Unit =
836- pendingTasks = task :: pendingTasks
843+ if ! checkedTasks.contains(task) then pendingTasks = task :: pendingTasks
837844
838845 /** Process the worklist until done */
839846 @ tailrec
840847 final def work ()(using State , Context ): Unit =
841848 pendingTasks match
842849 case task :: rest =>
850+ checkedTasks = checkedTasks + task
851+
843852 val heapBefore = heap.snapshot()
844853 val res = doTask(task)
845854 res.errors.foreach(_.issue)
@@ -861,7 +870,7 @@ object Semantic {
861870 * This method should only be called from the work list scheduler.
862871 */
863872 private def doTask (task : Task )(using State , Context ): Result = log(" checking " + task) {
864- val thisRef = task
873+ val thisRef = task.value
865874 val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
866875
867876 val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
@@ -878,7 +887,7 @@ object Semantic {
878887// ----- API --------------------------------
879888
880889 /** Add a checking task to the work list */
881- def addTask (task : ThisRef )(using WorkList ) = workList.addTask(task )
890+ def addTask (thisRef : ThisRef )(using WorkList , Trace ) = workList.addTask(Task (thisRef)(trace) )
882891
883892 /** Perform check on the work list until it becomes empty
884893 *
0 commit comments