@@ -162,7 +162,7 @@ object Objects:
162
162
val joinedTrace = data.pendingTraces.slice(index + 1 , data.checkingObjects.size).foldLeft(pendingTrace) { (a, acc) => acc ++ a }
163
163
val callTrace = Trace .buildStacktrace(joinedTrace, " Calling trace:\n " )
164
164
val cycle = data.checkingObjects.slice(index, data.checkingObjects.size)
165
- val pos = clazz.defTree. asInstanceOf [ TypeDef ].rhs. asInstanceOf [ Template ].constr
165
+ val pos = clazz.defTree
166
166
report.warning(" Cyclic initialization: " + cycle.map(_.show).mkString(" -> " ) + " -> " + clazz.show + " . " + callTrace, pos)
167
167
else if index == - 1 && data.checkedObjects.indexOf(clazz) == - 1 then
168
168
data.pendingTraces += pendingTrace
@@ -186,12 +186,15 @@ object Objects:
186
186
187
187
def show (using Context ): String
188
188
189
- /** Local environments can be deeply nested, therefore we need `outer`. */
190
- private case class LocalEnv (private [Env ] val params : Map [Symbol , Value ], owner : Symbol , outer : Data )(using Context ) extends Data :
189
+ /** Local environments can be deeply nested, therefore we need `outer`.
190
+ *
191
+ * For local variables in rhs of class field definitions, the `meth` is the primary constructor.
192
+ */
193
+ private case class LocalEnv (private [Env ] val params : Map [Symbol , Value ], meth : Symbol , outer : Data )(using Context ) extends Data :
191
194
val level = outer.level + 1
192
195
193
196
if (level > 3 )
194
- report.warning(" [Internal error] Deeply nested environemnt, level = " + level + " , " + owner .show + " in " + owner .enclosingClass.show, owner .defTree)
197
+ report.warning(" [Internal error] Deeply nested environemnt, level = " + level + " , " + meth .show + " in " + meth .enclosingClass.show, meth .defTree)
195
198
196
199
private [Env ] val locals : mutable.Map [Symbol , Value ] = mutable.Map .empty
197
200
@@ -203,10 +206,10 @@ object Objects:
203
206
params.contains(x) || locals.contains(x)
204
207
205
208
def widen (height : Int )(using Context ): Data =
206
- new LocalEnv (params.map(_ -> _.widen(height)), owner , outer.widen(height))
209
+ new LocalEnv (params.map(_ -> _.widen(height)), meth , outer.widen(height))
207
210
208
211
def show (using Context ) =
209
- " owner: " + owner .show + " \n " +
212
+ " owner: " + meth .show + " \n " +
210
213
" params: " + params.map(_.show + " ->" + _.show).mkString(" {" , " , " , " }" ) + " \n " +
211
214
" locals: " + locals.map(_.show + " ->" + _.show).mkString(" {" , " , " , " }" ) + " \n " +
212
215
" outer = {\n " + outer.show + " \n }"
@@ -265,19 +268,19 @@ object Objects:
265
268
* @param thisV The value for `this` of the enclosing class where the local variable is referenced.
266
269
* @param env The local environment where the local variable is referenced.
267
270
*/
268
- def resolveEnv (owner : Symbol , thisV : Value , env : Data )(using Context ): Option [(Value , Data )] =
271
+ def resolveEnv (meth : Symbol , thisV : Value , env : Data )(using Context ): Option [(Value , Data )] = log( " Resolving env for " + meth.show + " , this = " + thisV.show + " , env = " + env.show, printer) {
269
272
env match
270
273
case localEnv : LocalEnv =>
271
- if localEnv.owner == owner then Some (thisV -> env)
272
- else resolveEnv(owner , thisV, localEnv.outer)
274
+ if localEnv.meth == meth then Some (thisV -> env)
275
+ else resolveEnv(meth , thisV, localEnv.outer)
273
276
case NoEnv =>
274
277
// TODO: handle RefSet
275
278
thisV match
276
279
case ref : OfClass =>
277
- resolveEnv(owner , ref.outer, ref.env)
280
+ resolveEnv(meth , ref.outer, ref.env)
278
281
case _ =>
279
282
None
280
- end resolveEnv
283
+ }
281
284
282
285
def withEnv [T ](env : Data )(fn : Data ?=> T ): T = fn(using env)
283
286
end Env
@@ -587,7 +590,8 @@ object Objects:
587
590
if klass.owner.isClass then
588
591
(outer.widen(1 ), Env .NoEnv )
589
592
else
590
- Env .resolveEnv(klass.enclosingMethod, outer, summon[Env .Data ]).getOrElse(Cold -> Env .NoEnv )
593
+ // klass.enclosingMethod returns its primary constructor
594
+ Env .resolveEnv(klass.owner.enclosingMethod, outer, summon[Env .Data ]).getOrElse(Cold -> Env .NoEnv )
591
595
592
596
val instance = OfClass (klass, outerWidened, ctor, args.map(_.value), envWidened, State .currentObject)
593
597
callConstructor(instance, ctor, args)
@@ -631,7 +635,6 @@ object Objects:
631
635
def writeLocal (thisV : Value , sym : Symbol , value : Value ): Contextual [Value ] = log(" write local " + sym.show + " with " + value.show, printer, (_ : Value ).show) {
632
636
633
637
assert(sym.is(Flags .Mutable ), " Writing to immutable variable " + sym.show)
634
-
635
638
Env .resolveEnv(sym.enclosingMethod, thisV, summon[Env .Data ]) match
636
639
case Some (thisV -> env) =>
637
640
thisV match
@@ -660,7 +663,7 @@ object Objects:
660
663
def iterate ()(using Context ): Unit =
661
664
count += 1
662
665
663
- given Trace = Trace .empty.add(tpl.constr )
666
+ given Trace = Trace .empty.add(classSym.defTree )
664
667
given env : Env .Data = Env .emptyEnv(tpl.constr.symbol)
665
668
666
669
log(" Iteration " + count) {
0 commit comments