@@ -122,11 +122,10 @@ object Semantic {
122122 // Somehow Dotty uses the one in the class parameters
123123 given Heap = state.heap
124124 if objekt.outers.size <= 1 then
125- val tpl = klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
126- val termParamss = ctor.defTree.asInstanceOf [DefDef ].termParamss
127- val paramValues = termParamss.flatten.zip(args).map((param, v) => param.symbol -> v).toMap
128- given Env = Env (paramValues)
129- init(tpl, this , klass)
125+ state.populateWarm {
126+ val tpl = klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
127+ this .callConstructor(ctor, args.map(arg => ArgInfo (arg, EmptyTree )), tpl)
128+ }
130129 end if
131130 this
132131 }
@@ -184,8 +183,6 @@ object Semantic {
184183 */
185184 def prepare (heapBefore : Heap )(using State , Context ) =
186185 this .map.keys.foreach {
187- case thisRef : ThisRef =>
188- this .map = this .map - thisRef
189186 case warm : Warm if ! heapBefore.contains(warm) =>
190187 this .map = this .map - warm
191188 given Env = Env .empty
@@ -195,6 +192,13 @@ object Semantic {
195192 case _ =>
196193 }
197194
195+ // ThisRef might be used in `ensureInit`
196+ this .map.keys.foreach {
197+ case thisRef : ThisRef =>
198+ this .map = this .map - thisRef
199+ case _ =>
200+ }
201+
198202 override def toString () = map.toString()
199203 }
200204
@@ -426,7 +430,16 @@ object Semantic {
426430
427431// ----- State --------------------------------------------
428432 /** Global state of the checker */
429- class State (val cache : Cache , val heap : Heap , val workList : WorkList )
433+ class State (val cache : Cache , val heap : Heap , val workList : WorkList , var isPopulatingWarm : Boolean = false ) {
434+ // TODO: problematic for nested `init`.
435+ def populateWarm [T ](fun : State ?=> T ) = {
436+ val last = isPopulatingWarm
437+ isPopulatingWarm = true
438+ val res = fun(using this )
439+ isPopulatingWarm = last
440+ res
441+ }
442+ }
430443
431444 given (using s : State ): Heap = s.heap
432445 given (using s : State ): Cache = s.cache
@@ -608,7 +621,7 @@ object Semantic {
608621 report.error(" unexpected constructor call, meth = " + ctor + " , value = " + value, source)
609622 Result (Hot , Nil )
610623
611- case ref : Warm =>
624+ case ref : Warm if state.isPopulatingWarm =>
612625 val trace1 = trace.add(source)
613626 if ctor.hasSource then
614627 given Trace = trace1
@@ -627,20 +640,18 @@ object Semantic {
627640 else
628641 Result (Hot , Nil )
629642
630- case ref : ThisRef =>
643+ case ref : Ref =>
631644 val trace1 = trace.add(source)
632645 if ctor.hasSource then
633646 given Trace = trace1
634647 val cls = ctor.owner.enclosingClass.asClass
635648 val ddef = ctor.defTree.asInstanceOf [DefDef ]
636- val env2 = Env (ddef, args.map(_.value).widenArgs)
649+ given Env = Env (ddef, args.map(_.value).widenArgs)
637650 if ctor.isPrimaryConstructor then
638- given Env = env2
639651 val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
640652 val res = withTrace(trace.add(cls.defTree)) { eval(tpl, ref, cls, cacheResult = true ) }
641653 Result (ref, res.errors)
642654 else
643- given Env = env2
644655 eval(ddef.rhs, ref, cls, cacheResult = true )
645656 else if ref.canIgnoreMethodCall(ctor) then
646657 Result (Hot , Nil )
@@ -670,29 +681,29 @@ object Semantic {
670681 Result (Hot , Errors .empty)
671682 else
672683 val outer = Hot
673- val warm = Warm (klass, outer, ctor, args2).ensureInit()
684+ val warm = Warm (klass, outer, ctor, args2)
674685 val argInfos2 = args.zip(args2).map { (argInfo, v) => argInfo.copy(value = v) }
675- val task = ThisRef (klass, outer, ctor, args2)
676- this .addTask(task)
677- Result (warm, Errors .empty)
686+ val res = warm.callConstructor(ctor, argInfos2, source)
687+ Result (warm, res.errors)
678688
679689 case Cold =>
680690 val error = CallCold (ctor, source, trace1.toVector)
681691 Result (Hot , error :: Nil )
682692
683693 case ref : Ref =>
684694 given Trace = trace1
685- // widen the outer to finitize addresses
695+ // widen the outer to finitize the domain
686696 val outer = ref match
687- case Warm (_, _ : Warm , _, _) => Cold
697+ case warm @ Warm (_, _ : Ref , _, _) =>
698+ // the widened warm object might not exist in the heap
699+ warm.copy(outer = Cold ).ensureObjectExists().ensureInit()
688700 case _ => ref
689701
690702 val argsWidened = args.map(_.value).widenArgs
691703 val argInfos2 = args.zip(argsWidened).map { (argInfo, v) => argInfo.copy(value = v) }
692- val warm = Warm (klass, outer, ctor, argsWidened).ensureInit()
693- val task = ThisRef (klass, outer, ctor, argsWidened)
694- this .addTask(task)
695- Result (warm, Errors .empty)
704+ val warm = Warm (klass, outer, ctor, argsWidened)
705+ val res = warm.callConstructor(ctor, argInfos2, source)
706+ Result (warm, res.errors)
696707
697708 case Fun (body, thisV, klass, env) =>
698709 report.error(" unexpected tree in instantiating a function, fun = " + body.show, source)
@@ -1389,7 +1400,7 @@ object Semantic {
13891400 var fieldsChanged = true
13901401
13911402 // class body
1392- if ( ! thisV.isWarm) tpl.body.foreach {
1403+ if ! state.isPopulatingWarm then tpl.body.foreach {
13931404 case vdef : ValDef if ! vdef.symbol.is(Flags .Lazy ) && ! vdef.rhs.isEmpty =>
13941405 given Env = Env .empty
13951406 val res = eval(vdef.rhs, thisV, klass)
@@ -1400,7 +1411,7 @@ object Semantic {
14001411 case _ : MemberDef =>
14011412
14021413 case tree =>
1403- if fieldsChanged then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1414+ if fieldsChanged && ! thisV.isWarm then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
14041415 fieldsChanged = false
14051416
14061417 given Env = Env .empty
0 commit comments