Skip to content

Commit 9bd05b6

Browse files
committed
Add region context to objects
1 parent b378843 commit 9bd05b6

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import NameKinds.OuterSelectName
1111
import NameKinds.SuperAccessorName
1212

1313
import ast.tpd.*
14+
import util.SourcePosition
1415
import config.Printers.init as printer
1516
import reporting.StoreReporter
1617
import reporting.trace as log
@@ -122,30 +123,34 @@ object Objects:
122123
/**
123124
* Rerepsents values that are instances of the specified class.
124125
*
126+
* For immutable classes (classes without mutable fields, non-transitive), the parameter regions
127+
* is always empty and `owner` is `NoSymbol`.
128+
*
125129
* Note that the 2nd parameter block does not take part in the definition of equality.
126130
*/
127-
case class OfClass private (klass: ClassSymbol, outer: Value, ctor: Symbol, args: List[Value], env: Env.Data)
128-
(valsMap: mutable.Map[Symbol, Value], varsMap: mutable.Map[Symbol, Heap.Addr], outersMap: mutable.Map[ClassSymbol, Value])
131+
case class OfClass private (
132+
klass: ClassSymbol, outer: Value, ctor: Symbol, args: List[Value], env: Env.Data,
133+
regions: Regions.Data, owner: Symbol)(
134+
valsMap: mutable.Map[Symbol, Value], varsMap: mutable.Map[Symbol, Heap.Addr], outersMap: mutable.Map[ClassSymbol, Value])
129135
extends Ref(valsMap, varsMap, outersMap):
130136
def widenedCopy(outer: Value, args: List[Value], env: Env.Data): OfClass =
131-
new OfClass(klass, outer, ctor, args, env)(this.valsMap, this.varsMap, outersMap)
137+
new OfClass(klass, outer, ctor, args, env, regions, owner)(this.valsMap, this.varsMap, outersMap)
132138

133139
def show(using Context) =
134140
val valFields = vals.map(_.show + " -> " + _.show)
135141
"OfClass(" + klass.show + ", outer = " + outer + ", args = " + args.map(_.show) + ", vals = " + valFields + ")"
136142

137143
object OfClass:
138144
def apply(
139-
klass: ClassSymbol, outer: Value, ctor: Symbol, args: List[Value], env: Env.Data)(
145+
klass: ClassSymbol, outer: Value, ctor: Symbol, args: List[Value], env: Env.Data, regions: Regions.Data, owner: Symbol)(
140146
using Context
141147
): OfClass =
142-
val instance = new OfClass(klass, outer, ctor, args, env)(
148+
val instance = new OfClass(klass, outer, ctor, args, env, regions, owner)(
143149
valsMap = mutable.Map.empty, varsMap = mutable.Map.empty, outersMap = mutable.Map.empty
144150
)
145151
instance.initOuter(klass, outer)
146152
instance
147153

148-
149154
/**
150155
* Rerepsents arrays.
151156
*
@@ -468,9 +473,20 @@ object Objects:
468473
result.value
469474
end Cache
470475

476+
/**
477+
* Region context for mutable states
478+
*
479+
* By default, the region context is empty.
480+
*/
481+
object Regions:
482+
opaque type Data = List[SourcePosition]
483+
val empty: Data = Nil
484+
def extend(pos: SourcePosition)(using data: Data): Data = pos :: data
485+
def exists(pos: SourcePosition)(using data: Data): Data = data.indexOf(pos) >= 0
486+
471487
inline def cache(using c: Cache.Data): Cache.Data = c
472488

473-
type Contextual[T] = (Context, State.Data, Env.Data, Cache.Data, Heap.MutableData, Trace) ?=> T
489+
type Contextual[T] = (Context, State.Data, Env.Data, Cache.Data, Heap.MutableData, Regions.Data, Trace) ?=> T
474490

475491
// --------------------------- domain operations -----------------------------
476492

@@ -499,7 +515,7 @@ object Objects:
499515
if height == 0 then Cold
500516
else Fun(code, thisV.widen(height), klass, env.widen(height))
501517

502-
case ref @ OfClass(klass, outer, init, args, env) =>
518+
case ref @ OfClass(klass, outer, _, args, env, _, _) =>
503519
if height == 0 then
504520
Cold
505521
else
@@ -731,7 +747,11 @@ object Objects:
731747
// klass.enclosingMethod returns its primary constructor
732748
Env.resolveEnv(klass.owner.enclosingMethod, outer, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
733749

734-
val instance = OfClass(klass, outerWidened, ctor, args.map(_.value), envWidened)
750+
// Immutable objects do not care about owners and context
751+
val owner = if isMutable(klass) then State.currentObject else NoSymbol
752+
val regions = if isMutable(klass) then summon[Regions.Data] else Regions.empty
753+
754+
val instance = OfClass(klass, outerWidened, ctor, args.map(_.value), envWidened, regions, owner)
735755
callConstructor(instance, ctor, args)
736756
instance
737757

compiler/src/dotty/tools/dotc/transform/init/Util.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,8 @@ object Util:
100100

101101
// A concrete class may not be instantiated if the self type is not satisfied
102102
instantiable && cls.enclosingPackageClass != defn.StdLibPatchesPackage.moduleClass
103+
104+
/** Whether the class or its super class/trait contains any mutable fields? */
105+
def isMutable(cls: ClassSymbol)(using Context): Boolean =
106+
cls.classInfo.decls.exists(_.is(Flags.Mutable)) ||
107+
cls.parentSyms.exists(parentCls => isMutable(parentCls))

0 commit comments

Comments
 (0)