Skip to content

Commit 62a6513

Browse files
committed
Refactor VarState
- Drop Frozen enum - Make VarState subclasses inner classes of companion object - Rename them - Give implicit parameter VarState of subCapture method a default value
1 parent 2da4277 commit 62a6513

File tree

7 files changed

+101
-121
lines changed

7 files changed

+101
-121
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import config.Feature
1616
import collection.mutable
1717
import CCState.*
1818
import reporting.Message
19-
import CaptureSet.Frozen
19+
import CaptureSet.VarState
2020

2121
/** Attachment key for capturing type trees */
2222
private val Captures: Key[CaptureSet] = Key()
@@ -251,7 +251,7 @@ extension (tp: Type)
251251
* the two capture sets are combined.
252252
*/
253253
def capturing(cs: CaptureSet)(using Context): Type =
254-
if (cs.isAlwaysEmpty || cs.isConst && cs.subCaptures(tp.captureSet, Frozen.All).isOK)
254+
if (cs.isAlwaysEmpty || cs.isConst && cs.subCaptures(tp.captureSet, VarState.Separate).isOK)
255255
&& !cs.keepAlways
256256
then tp
257257
else tp match

compiler/src/dotty/tools/dotc/cc/CaptureRef.scala

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import CCState.*
1313
import Periods.NoRunId
1414
import compiletime.uninitialized
1515
import StdNames.nme
16+
import CaptureSet.VarState
1617

1718
/** A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs,
1819
* as well as three kinds of AnnotatedTypes representing readOnly, reach, and maybe capabilities.
@@ -134,8 +135,6 @@ trait CaptureRef extends TypeProxy, ValueType:
134135
final def invalidateCaches() =
135136
myCaptureSetRunId = NoRunId
136137

137-
import CaptureSet.{VarState, FrozenAllState}
138-
139138
/** x subsumes x
140139
* x =:= y ==> x subsumes y
141140
* x subsumes y ==> x subsumes y.f
@@ -150,7 +149,7 @@ trait CaptureRef extends TypeProxy, ValueType:
150149
*
151150
* TODO: Move to CaptureSet
152151
*/
153-
final def subsumes(y: CaptureRef)(using ctx: Context, vs: VarState = FrozenAllState): Boolean =
152+
final def subsumes(y: CaptureRef)(using ctx: Context, vs: VarState = VarState.Separate): Boolean =
154153

155154
def subsumingRefs(x: Type, y: Type): Boolean = x match
156155
case x: CaptureRef => y match
@@ -166,7 +165,7 @@ trait CaptureRef extends TypeProxy, ValueType:
166165
case _ => false
167166

168167
(this eq y)
169-
|| maxSubsumes(y, canAddHidden = vs.frozen == CaptureSet.Frozen.Vars)
168+
|| maxSubsumes(y, canAddHidden = !vs.isOpen)
170169
|| y.match
171170
case y: TermRef if !y.isCap =>
172171
y.prefix.match
@@ -223,18 +222,11 @@ trait CaptureRef extends TypeProxy, ValueType:
223222
* the test again with canAddHidden = true as a last effort before we
224223
* fail a comparison.
225224
*/
226-
def maxSubsumes(y: CaptureRef, canAddHidden: Boolean)(using ctx: Context, vs: VarState = FrozenAllState): Boolean =
225+
def maxSubsumes(y: CaptureRef, canAddHidden: Boolean)(using ctx: Context, vs: VarState = VarState.Separate): Boolean =
227226
this.match
228227
case Fresh.Cap(hidden) =>
229-
if vs.ifNotSeen(this)(hidden.elems.exists(_.subsumes(y))) then true
230-
else if !y.stripReadOnly.isCap && hidden.recordElemsState() then
231-
if canAddHidden then
232-
if vs != CaptureSet.FrozenUnrecordedHiddenState then
233-
hidden.elems += y
234-
true
235-
else
236-
false
237-
else false
228+
vs.ifNotSeen(this)(hidden.elems.exists(_.subsumes(y)))
229+
|| !y.stripReadOnly.isCap && canAddHidden && vs.addHidden(hidden, y)
238230
case _ =>
239231
this.isCap && canAddHidden
240232
|| y.match

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 69 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ sealed abstract class CaptureSet extends Showable:
147147
* capture set.
148148
*/
149149
protected final def addNewElem(elem: CaptureRef)(using ctx: Context, vs: VarState): CompareResult =
150-
if elem.isMaxCapability || vs.frozen != Frozen.None then
150+
if elem.isMaxCapability || !vs.isOpen then
151151
addThisElem(elem)
152152
else
153153
addThisElem(elem).orElse:
@@ -168,7 +168,7 @@ sealed abstract class CaptureSet extends Showable:
168168
protected def addThisElem(elem: CaptureRef)(using Context, VarState): CompareResult
169169

170170
protected def addHiddenElem(elem: CaptureRef)(using ctx: Context, vs: VarState): CompareResult =
171-
if elems.exists(_.maxSubsumes(elem, canAddHidden = vs.frozen != Frozen.All))
171+
if elems.exists(_.maxSubsumes(elem, canAddHidden = true))
172172
then CompareResult.OK
173173
else CompareResult.Fail(this :: Nil)
174174

@@ -177,13 +177,13 @@ sealed abstract class CaptureSet extends Showable:
177177

178178
/** If `cs` is a variable, add this capture set as one of its dependent sets */
179179
protected def addAsDependentTo(cs: CaptureSet)(using Context): this.type =
180-
cs.addDependent(this)(using ctx, UnrecordedState)
180+
cs.addDependent(this)(using ctx, VarState.Unrecorded)
181181
this
182182

183183
/** {x} <:< this where <:< is subcapturing, but treating all variables
184184
* as frozen.
185185
*/
186-
def accountsFor(x: CaptureRef)(using ctx: Context, vs: VarState = FrozenAllState): Boolean =
186+
def accountsFor(x: CaptureRef)(using ctx: Context, vs: VarState = VarState.Separate): Boolean =
187187

188188
/** Like `refs.exists(p)`, but testing fresh cap instances in refs last */
189189
def existsElem(refs: SimpleIdentitySet[CaptureRef], p: CaptureRef => Boolean): Boolean =
@@ -201,9 +201,9 @@ sealed abstract class CaptureSet extends Showable:
201201
existsElem(elems, _.subsumes(x))
202202
|| !x.isMaxCapability
203203
&& !x.derivesFrom(defn.Caps_CapSet)
204-
&& !(vs.frozen == Frozen.All && x.captureSetOfInfo.containsRootCapability)
205-
// under Frozen.All, don't try to widen to cap since that might succeed with {cap} <: {cap}
206-
&& x.captureSetOfInfo.subCaptures(this, Frozen.All).isOK
204+
&& !(vs == VarState.Separate && x.captureSetOfInfo.containsRootCapability)
205+
// in VarState.Separate, don't try to widen to cap since that might succeed with {cap} <: {cap}
206+
&& x.captureSetOfInfo.subCaptures(this, VarState.Separate).isOK
207207

208208
comparer match
209209
case comparer: ExplainingTypeComparer => comparer.traceIndented(debugInfo)(test)
@@ -219,7 +219,7 @@ sealed abstract class CaptureSet extends Showable:
219219
*/
220220
def mightAccountFor(x: CaptureRef)(using Context): Boolean =
221221
reporting.trace(i"$this mightAccountFor $x, ${x.captureSetOfInfo}?", show = true):
222-
elems.exists(_.subsumes(x)(using ctx, FrozenUnrecordedHiddenState))
222+
elems.exists(_.subsumes(x)(using ctx, VarState.ClosedUnrecorded))
223223
|| !x.isMaxCapability
224224
&& {
225225
val elems = x.captureSetOfInfo.elems
@@ -240,15 +240,11 @@ sealed abstract class CaptureSet extends Showable:
240240
* be added when making this test. An attempt to add either
241241
* will result in failure.
242242
*/
243-
final def subCaptures(that: CaptureSet, frozen: Frozen)(using Context): CompareResult =
244-
val state = frozen match
245-
case Frozen.None => VarState()
246-
case Frozen.Vars => FrozenVarState()
247-
case Frozen.All => FrozenAllState
248-
subCaptures(that)(using ctx, state)
243+
final def subCaptures(that: CaptureSet, vs: VarState)(using Context): CompareResult =
244+
subCaptures(that)(using ctx, vs)
249245

250246
/** The subcapturing test, using a given VarState */
251-
private def subCaptures(that: CaptureSet)(using Context, VarState): CompareResult =
247+
def subCaptures(that: CaptureSet)(using ctx: Context, vs: VarState = VarState()): CompareResult =
252248
val result = that.tryInclude(elems, this)
253249
if result.isOK then
254250
addDependent(that)
@@ -262,16 +258,16 @@ sealed abstract class CaptureSet extends Showable:
262258
* in a frozen state.
263259
*/
264260
def =:= (that: CaptureSet)(using Context): Boolean =
265-
this.subCaptures(that, Frozen.All).isOK
266-
&& that.subCaptures(this, Frozen.All).isOK
261+
this.subCaptures(that, VarState.Separate).isOK
262+
&& that.subCaptures(this, VarState.Separate).isOK
267263

268264
/** The smallest capture set (via <:<) that is a superset of both
269265
* `this` and `that`
270266
*/
271267
def ++ (that: CaptureSet)(using Context): CaptureSet =
272-
if this.subCaptures(that, Frozen.All).isOK then
268+
if this.subCaptures(that, VarState.Separate).isOK then
273269
if that.isAlwaysEmpty && this.keepAlways then this else that
274-
else if that.subCaptures(this, Frozen.All).isOK then this
270+
else if that.subCaptures(this, VarState.Separate).isOK then this
275271
else if this.isConst && that.isConst then Const(this.elems ++ that.elems)
276272
else Union(this, that)
277273

@@ -286,8 +282,8 @@ sealed abstract class CaptureSet extends Showable:
286282
/** The largest capture set (via <:<) that is a subset of both `this` and `that`
287283
*/
288284
def **(that: CaptureSet)(using Context): CaptureSet =
289-
if this.subCaptures(that, Frozen.Vars).isOK then this
290-
else if that.subCaptures(this, Frozen.Vars).isOK then that
285+
if this.subCaptures(that, VarState.Closed()).isOK then this
286+
else if that.subCaptures(this, VarState.Closed()).isOK then that
291287
else if this.isConst && that.isConst then Const(elemIntersection(this, that))
292288
else Intersection(this, that)
293289

@@ -556,7 +552,7 @@ object CaptureSet:
556552
else
557553
// id == 108 then assert(false, i"trying to add $elem to $this")
558554
assert(elem.isTrackableRef, elem)
559-
assert(!this.isInstanceOf[HiddenSet] || summon[VarState] == FrozenAllState, summon[VarState])
555+
assert(!this.isInstanceOf[HiddenSet] || summon[VarState] == VarState.Separate, summon[VarState])
560556
elems += elem
561557
if elem.isRootCapability then
562558
rootAddedHandler()
@@ -652,7 +648,8 @@ object CaptureSet:
652648
.showing(i"solve $this = $result", capt)
653649
//println(i"solving var $this $approx ${approx.isConst} deps = ${deps.toList}")
654650
val newElems = approx.elems -- elems
655-
if tryInclude(newElems, empty)(using ctx, VarState()).isOK then
651+
given VarState()
652+
if tryInclude(newElems, empty).isOK then
656653
markSolved()
657654

658655
/** Mark set as solved and propagate this info to all dependent sets */
@@ -939,10 +936,6 @@ object CaptureSet:
939936
/** A capture set variable used to record the references hidden by a Fresh.Cap instance */
940937
class HiddenSet(initialHidden: Refs = emptySet)(using @constructorOnly ictx: Context)
941938
extends Var(initialElems = initialHidden):
942-
override def recordElemsState()(using VarState): Boolean =
943-
varState.getElems(this) match
944-
case None => varState.putHidden(this, elems)
945-
case _ => true
946939

947940
/** Apply function `f` to `elems` while setting `elems` to empty for the
948941
* duration. This is used to escape infinite recursions if two Frash.Caps
@@ -990,7 +983,7 @@ object CaptureSet:
990983
*/
991984
def subCapturesRange(arg1: TypeBounds, arg2: Type)(using Context): Boolean = arg1 match
992985
case TypeBounds(CapturingType(lo, loRefs), CapturingType(hi, hiRefs)) if lo =:= hi =>
993-
given VarState = VarState()
986+
given VarState()
994987
val cs2 = arg2.captureSet
995988
hiRefs.subCaptures(cs2).isOK && cs2.subCaptures(loRefs).isOK
996989
case _ =>
@@ -1048,19 +1041,11 @@ object CaptureSet:
10481041
case _ => this
10491042
end CompareResult
10501043

1051-
/** An enum indicating a Frozen degree for subCapturing tests */
1052-
enum Frozen:
1053-
case None // operations are performed in a regular VarState
1054-
case Vars // operations are performed in a FrozenVarState
1055-
case All // operations are performed in FrozenAllState
1056-
10571044
/** A VarState serves as a snapshot mechanism that can undo
10581045
* additions of elements or super sets if an operation fails
10591046
*/
10601047
class VarState:
10611048

1062-
def frozen: Frozen = Frozen.None
1063-
10641049
/** A map from captureset variables to their elements at the time of the snapshot. */
10651050
protected val elemsMap: util.EqHashMap[Var, Refs] = new util.EqHashMap
10661051

@@ -1089,11 +1074,19 @@ object CaptureSet:
10891074
*/
10901075
def putDeps(v: Var, deps: Deps): Boolean = { depsMap(v) = deps; true }
10911076

1092-
/** Record hidden elements in elemsMap of hidden set `v`,
1077+
/** Does this state allow additions of elements to capture set variables? */
1078+
def isOpen = true
1079+
1080+
/** Add element to hidden set, recording it in elemsMap,
10931081
* return whether this was allowed. By default, recording is allowed
1094-
* but the special state FrozenAllState overrides this.
1082+
* but the special state VarState.Separate overrides this.
10951083
*/
1096-
def putHidden(v: HiddenSet, elems: Refs): Boolean = { elemsMap(v) = elems; true }
1084+
def addHidden(hidden: HiddenSet, elem: CaptureRef): Boolean =
1085+
elemsMap.get(hidden) match
1086+
case None => elemsMap(hidden) = hidden.elems
1087+
case _ =>
1088+
hidden.elems += elem
1089+
true
10971090

10981091
/** Roll back global state to what was recorded in this VarState */
10991092
def rollBack(): Unit =
@@ -1107,45 +1100,48 @@ object CaptureSet:
11071100
if seen.add(ref) then
11081101
try pred finally seen -= ref
11091102
else false
1110-
end VarState
11111103

1112-
/** A class for states that do not allow to record elements or dependent sets.
1113-
* In effect this means that no new elements or dependent sets can be added
1114-
* in these states (since the previous state cannot be recorded in a snapshot)
1115-
* On the other hand, these states do allow by default Fresh.Cap instances to
1116-
* subsume arbitary types, which are then recorded in their hidden sets.
1117-
*/
1118-
class FrozenVarState extends VarState:
1119-
override def frozen = Frozen.Vars
1120-
override def putElems(v: Var, refs: Refs) = false
1121-
override def putDeps(v: Var, deps: Deps) = false
1122-
override def putHidden(v: HiddenSet, elems: Refs): Boolean = { elemsMap(v) = elems; true }
1104+
object VarState:
11231105

1124-
@sharable
1125-
/** A frozen state that allows a Fresh.Cap instancce to subsume a
1126-
* reference `r` only if `r` is already present in the hidden set of the instance.
1127-
* No new references can be added.
1128-
*/
1129-
object FrozenAllState extends FrozenVarState:
1130-
override def frozen = Frozen.All
1131-
override def putHidden(v: HiddenSet, elems: Refs): Boolean = false
1106+
/** A class for states that do not allow to record elements or dependent sets.
1107+
* In effect this means that no new elements or dependent sets can be added
1108+
* in these states (since the previous state cannot be recorded in a snapshot)
1109+
* On the other hand, these states do allow by default Fresh.Cap instances to
1110+
* subsume arbitary types, which are then recorded in their hidden sets.
1111+
*/
1112+
class Closed extends VarState:
1113+
override def putElems(v: Var, refs: Refs) = false
1114+
override def putDeps(v: Var, deps: Deps) = false
1115+
override def isOpen = false
1116+
1117+
/** A closed state that allows a Fresh.Cap instance to subsume a
1118+
* reference `r` only if `r` is already present in the hidden set of the instance.
1119+
* No new references can be added.
1120+
*/
1121+
@sharable
1122+
object Separate extends Closed:
1123+
override def addHidden(hidden: HiddenSet, elem: CaptureRef): Boolean = false
11321124

1133-
@sharable
1134-
/** A frozen state that allows a Fresh.Cap instancce to subsume a
1135-
* reference `r` only if `r` is already present in the hidden set of the instance.
1136-
* No new references can be added.
1137-
*/
1138-
object FrozenUnrecordedHiddenState extends FrozenVarState
1125+
/** A special state that turns off recording of elements. Used only
1126+
* in `addSub` to prevent cycles in recordings.
1127+
*/
1128+
@sharable
1129+
private[CaptureSet] object Unrecorded extends VarState:
1130+
override def putElems(v: Var, refs: Refs) = true
1131+
override def putDeps(v: Var, deps: Deps) = true
1132+
override def rollBack(): Unit = ()
1133+
override def addHidden(hidden: HiddenSet, elem: CaptureRef): Boolean = true
1134+
1135+
/** A closed state that turns off recording of hidden elements (but allows
1136+
* adding them). Used in `mightAccountFor`.
1137+
*/
1138+
@sharable
1139+
private[CaptureSet] object ClosedUnrecorded extends Closed:
1140+
override def addHidden(hidden: HiddenSet, elem: CaptureRef): Boolean = true
11391141

1140-
@sharable
1141-
/** A special state that turns off recording of elements. Used only
1142-
* in `addSub` to prevent cycles in recordings.
1143-
*/
1144-
private object UnrecordedState extends VarState:
1145-
override def putElems(v: Var, refs: Refs) = true
1146-
override def putDeps(v: Var, deps: Deps) = true
1147-
override def rollBack(): Unit = ()
1142+
end VarState
11481143

1144+
@sharable
11491145
/** The current VarState, as passed by the implicit context */
11501146
def varState(using state: VarState): VarState = state
11511147

0 commit comments

Comments
 (0)