@@ -197,7 +197,7 @@ class Objects:
197197 *
198198 * @param owner The static object whose initialization creates the array.
199199 */
200- case class OfArray (owner : ClassSymbol , regions : Regions .Data )(using @ constructorOnly ctx : Context ) extends ValueElement :
200+ case class OfArray (owner : ClassSymbol , regions : Regions .Data )(using @ constructorOnly ctx : Context , @ constructorOnly trace : Trace ) extends ValueElement :
201201 val klass : ClassSymbol = defn.ArrayClass
202202 val addr : Heap .Addr = Heap .arrayAddr(regions, owner)
203203 def show (using Context ) = " OfArray(owner = " + owner.show + " )"
@@ -455,9 +455,11 @@ class Objects:
455455 abstract class Addr :
456456 /** The static object which owns the mutable slot */
457457 def owner : ClassSymbol
458+ def getTrace : Trace = Trace .empty
458459
459460 /** The address for mutable fields of objects. */
460- private case class FieldAddr (regions : Regions .Data , field : Symbol , owner : ClassSymbol ) extends Addr
461+ private case class FieldAddr (regions : Regions .Data , field : Symbol , owner : ClassSymbol )(trace : Trace ) extends Addr :
462+ override def getTrace : Trace = trace
461463
462464 /** The address for mutable local variables . */
463465 private case class LocalVarAddr (regions : Regions .Data , sym : Symbol , owner : ClassSymbol ) extends Addr
@@ -497,11 +499,11 @@ class Objects:
497499 def localVarAddr (regions : Regions .Data , sym : Symbol , owner : ClassSymbol ): Addr =
498500 LocalVarAddr (regions, sym, owner)
499501
500- def fieldVarAddr (regions : Regions .Data , sym : Symbol , owner : ClassSymbol ): Addr =
501- FieldAddr (regions, sym, owner)
502+ def fieldVarAddr (regions : Regions .Data , sym : Symbol , owner : ClassSymbol )( using Trace ) : Addr =
503+ FieldAddr (regions, sym, owner)(summon[ Trace ])
502504
503- def arrayAddr (regions : Regions .Data , owner : ClassSymbol )(using Context ): Addr =
504- FieldAddr (regions, defn.ArrayClass , owner)
505+ def arrayAddr (regions : Regions .Data , owner : ClassSymbol )(using Trace , Context ): Addr =
506+ FieldAddr (regions, defn.ArrayClass , owner)(summon[ Trace ])
505507
506508 def getHeapData ()(using mutable : MutableData ): Data = mutable.heap
507509
@@ -654,12 +656,12 @@ class Objects:
654656 if arr.addr.owner == State .currentObject then
655657 Heap .read(arr.addr)
656658 else
657- errorReadOtherStaticObject(State .currentObject, arr.addr.owner )
659+ errorReadOtherStaticObject(State .currentObject, arr.addr)
658660 Bottom
659661 else if target == defn.Array_update then
660662 assert(args.size == 2 , " Incorrect number of arguments for Array update, found = " + args.size)
661663 if arr.addr.owner != State .currentObject then
662- errorMutateOtherStaticObject(State .currentObject, arr.addr.owner )
664+ errorMutateOtherStaticObject(State .currentObject, arr.addr)
663665 else
664666 Heap .writeJoin(arr.addr, args.tail.head.value)
665667 Bottom
@@ -810,7 +812,7 @@ class Objects:
810812 if addr.owner == State .currentObject then
811813 Heap .read(addr)
812814 else
813- errorReadOtherStaticObject(State .currentObject, addr.owner )
815+ errorReadOtherStaticObject(State .currentObject, addr)
814816 Bottom
815817 else if ref.isObjectRef && ref.klass.hasSource then
816818 report.warning(" Access uninitialized field " + field.show + " . " + Trace .show, Trace .position)
@@ -879,7 +881,7 @@ class Objects:
879881 if ref.hasVar(field) then
880882 val addr = ref.varAddr(field)
881883 if addr.owner != State .currentObject then
882- errorMutateOtherStaticObject(State .currentObject, addr.owner )
884+ errorMutateOtherStaticObject(State .currentObject, addr)
883885 else
884886 Heap .writeJoin(addr, rhs)
885887 else
@@ -968,7 +970,7 @@ class Objects:
968970 if addr.owner == State .currentObject then
969971 Heap .read(addr)
970972 else
971- errorReadOtherStaticObject(State .currentObject, addr.owner )
973+ errorReadOtherStaticObject(State .currentObject, addr)
972974 Bottom
973975 end if
974976 case _ =>
@@ -1020,7 +1022,7 @@ class Objects:
10201022 Env .getVar(sym) match
10211023 case Some (addr) =>
10221024 if addr.owner != State .currentObject then
1023- errorMutateOtherStaticObject(State .currentObject, addr.owner )
1025+ errorMutateOtherStaticObject(State .currentObject, addr)
10241026 else
10251027 Heap .writeJoin(addr, value)
10261028 case _ =>
@@ -1757,20 +1759,31 @@ class Objects:
17571759 if cls.isAllOf(Flags .JavaInterface ) then Bottom
17581760 else evalType(tref.prefix, thisV, klass, elideObjectAccess = cls.isStatic)
17591761
1762+ def printTraceWhenMultiple (trace : Trace )(using Context ): String =
1763+ if trace.toVector.size > 1 then
1764+ Trace .buildStacktrace(trace, " The mutable state is created through: " + System .lineSeparator())
1765+ else " "
1766+
17601767 val mutateErrorSet : mutable.Set [(ClassSymbol , ClassSymbol )] = mutable.Set .empty
1761- def errorMutateOtherStaticObject (currentObj : ClassSymbol , otherObj : ClassSymbol )(using Trace , Context ) =
1768+ def errorMutateOtherStaticObject (currentObj : ClassSymbol , addr : Heap .Addr )(using Trace , Context ) =
1769+ val otherObj = addr.owner
1770+ val addr_trace = addr.getTrace
17621771 if mutateErrorSet.add((currentObj, otherObj)) then
17631772 val msg =
17641773 s " Mutating ${otherObj.show} during initialization of ${currentObj.show}. \n " +
1765- " Mutating other static objects during the initialization of one static object is forbidden. " + Trace .show
1774+ " Mutating other static objects during the initialization of one static object is forbidden. " + Trace .show +
1775+ printTraceWhenMultiple(addr_trace)
17661776
17671777 report.warning(msg, Trace .position)
17681778
17691779 val readErrorSet : mutable.Set [(ClassSymbol , ClassSymbol )] = mutable.Set .empty
1770- def errorReadOtherStaticObject (currentObj : ClassSymbol , otherObj : ClassSymbol )(using Trace , Context ) =
1780+ def errorReadOtherStaticObject (currentObj : ClassSymbol , addr : Heap .Addr )(using Trace , Context ) =
1781+ val otherObj = addr.owner
1782+ val addr_trace = addr.getTrace
17711783 if readErrorSet.add((currentObj, otherObj)) then
17721784 val msg =
17731785 " Reading mutable state of " + otherObj.show + " during initialization of " + currentObj.show + " .\n " +
1774- " Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " + Trace .show
1786+ " Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " + Trace .show +
1787+ printTraceWhenMultiple(addr_trace)
17751788
17761789 report.warning(msg, Trace .position)
0 commit comments