@@ -122,11 +122,10 @@ object Semantic {
122
122
// Somehow Dotty uses the one in the class parameters
123
123
given Heap = state.heap
124
124
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
+ }
130
129
end if
131
130
this
132
131
}
@@ -184,8 +183,6 @@ object Semantic {
184
183
*/
185
184
def prepare (heapBefore : Heap )(using State , Context ) =
186
185
this .map.keys.foreach {
187
- case thisRef : ThisRef =>
188
- this .map = this .map - thisRef
189
186
case warm : Warm if ! heapBefore.contains(warm) =>
190
187
this .map = this .map - warm
191
188
given Env = Env .empty
@@ -195,6 +192,13 @@ object Semantic {
195
192
case _ =>
196
193
}
197
194
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
+
198
202
override def toString () = map.toString()
199
203
}
200
204
@@ -426,7 +430,16 @@ object Semantic {
426
430
427
431
// ----- State --------------------------------------------
428
432
/** 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
+ }
430
443
431
444
given (using s : State ): Heap = s.heap
432
445
given (using s : State ): Cache = s.cache
@@ -608,7 +621,7 @@ object Semantic {
608
621
report.error(" unexpected constructor call, meth = " + ctor + " , value = " + value, source)
609
622
Result (Hot , Nil )
610
623
611
- case ref : Warm =>
624
+ case ref : Warm if state.isPopulatingWarm =>
612
625
val trace1 = trace.add(source)
613
626
if ctor.hasSource then
614
627
given Trace = trace1
@@ -627,20 +640,18 @@ object Semantic {
627
640
else
628
641
Result (Hot , Nil )
629
642
630
- case ref : ThisRef =>
643
+ case ref : Ref =>
631
644
val trace1 = trace.add(source)
632
645
if ctor.hasSource then
633
646
given Trace = trace1
634
647
val cls = ctor.owner.enclosingClass.asClass
635
648
val ddef = ctor.defTree.asInstanceOf [DefDef ]
636
- val env2 = Env (ddef, args.map(_.value).widenArgs)
649
+ given Env = Env (ddef, args.map(_.value).widenArgs)
637
650
if ctor.isPrimaryConstructor then
638
- given Env = env2
639
651
val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
640
652
val res = withTrace(trace.add(cls.defTree)) { eval(tpl, ref, cls, cacheResult = true ) }
641
653
Result (ref, res.errors)
642
654
else
643
- given Env = env2
644
655
eval(ddef.rhs, ref, cls, cacheResult = true )
645
656
else if ref.canIgnoreMethodCall(ctor) then
646
657
Result (Hot , Nil )
@@ -670,29 +681,29 @@ object Semantic {
670
681
Result (Hot , Errors .empty)
671
682
else
672
683
val outer = Hot
673
- val warm = Warm (klass, outer, ctor, args2).ensureInit()
684
+ val warm = Warm (klass, outer, ctor, args2)
674
685
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)
678
688
679
689
case Cold =>
680
690
val error = CallCold (ctor, source, trace1.toVector)
681
691
Result (Hot , error :: Nil )
682
692
683
693
case ref : Ref =>
684
694
given Trace = trace1
685
- // widen the outer to finitize addresses
695
+ // widen the outer to finitize the domain
686
696
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()
688
700
case _ => ref
689
701
690
702
val argsWidened = args.map(_.value).widenArgs
691
703
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)
696
707
697
708
case Fun (body, thisV, klass, env) =>
698
709
report.error(" unexpected tree in instantiating a function, fun = " + body.show, source)
@@ -1389,7 +1400,7 @@ object Semantic {
1389
1400
var fieldsChanged = true
1390
1401
1391
1402
// class body
1392
- if ( ! thisV.isWarm) tpl.body.foreach {
1403
+ if ! state.isPopulatingWarm then tpl.body.foreach {
1393
1404
case vdef : ValDef if ! vdef.symbol.is(Flags .Lazy ) && ! vdef.rhs.isEmpty =>
1394
1405
given Env = Env .empty
1395
1406
val res = eval(vdef.rhs, thisV, klass)
@@ -1400,7 +1411,7 @@ object Semantic {
1400
1411
case _ : MemberDef =>
1401
1412
1402
1413
case tree =>
1403
- if fieldsChanged then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1414
+ if fieldsChanged && ! thisV.isWarm then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1404
1415
fieldsChanged = false
1405
1416
1406
1417
given Env = Env .empty
0 commit comments