@@ -178,12 +178,7 @@ sealed abstract class CaptureSet extends Showable:
178178
179179 /** Try to include all element in `refs` to this capture set. */
180180 protected final def tryInclude (newElems : Refs , origin : CaptureSet )(using Context , VarState ): Boolean =
181- TypeComparer .inNestedLevel:
182- // Run in nested level so that a error notes for a failure here can be
183- // cancelled in case the whole comparison succeeds.
184- // We do this here because all nested tryInclude and subCaptures calls go
185- // through this method.
186- newElems.forall(tryInclude(_, origin))
181+ newElems.forall(tryInclude(_, origin))
187182
188183 protected def mutableToReader (origin : CaptureSet )(using Context ): Boolean =
189184 if mutability == Mutable then toReader() else true
@@ -284,16 +279,14 @@ sealed abstract class CaptureSet extends Showable:
284279
285280 /** The subcapturing test, using a given VarState */
286281 final def subCaptures (that : CaptureSet )(using ctx : Context , vs : VarState = VarState ()): Boolean =
287- val this1 = this .adaptMutability(that)
288- if this1 == null then false
289- else if this1 ne this then
290- capt.println(i " WIDEN ro $this with ${this .mutability} <:< $that with ${that.mutability} to $this1" )
291- this1.subCaptures(that, vs)
292- else if that.tryInclude(elems, this ) then
293- addDependent(that)
294- else
295- varState.rollBack()
296- false
282+ TypeComparer .inNestedLevel:
283+ val this1 = this .adaptMutability(that)
284+ if this1 == null then false
285+ else if this1 ne this then
286+ capt.println(i " WIDEN ro $this with ${this .mutability} <:< $that with ${that.mutability} to $this1" )
287+ this1.subCaptures(that, vs)
288+ else
289+ that.tryInclude(elems, this ) && addDependent(that)
297290
298291 /** Two capture sets are considered =:= equal if they mutually subcapture each other
299292 * in a frozen state.
@@ -662,30 +655,6 @@ object CaptureSet:
662655
663656 var description : String = " "
664657
665- /** Record current elements in given VarState provided it does not yet
666- * contain an entry for this variable.
667- */
668- private def recordElemsState ()(using VarState ): Boolean =
669- varState.getElems(this ) match
670- case None => varState.putElems(this , elems)
671- case _ => true
672-
673- /** Record current dependent sets in given VarState provided it does not yet
674- * contain an entry for this variable.
675- */
676- private [CaptureSet ] def recordDepsState ()(using VarState ): Boolean =
677- varState.getDeps(this ) match
678- case None => varState.putDeps(this , deps)
679- case _ => true
680-
681- /** Reset elements to what was recorded in `state` */
682- def resetElems ()(using state : VarState ): Unit =
683- elems = state.elems(this )
684-
685- /** Reset dependent sets to what was recorded in `state` */
686- def resetDeps ()(using state : VarState ): Unit =
687- deps = state.deps(this )
688-
689658 /** Check that all maps recorded in skippedMaps map `elem` to itself
690659 * or something subsumed by it.
691660 */
@@ -695,16 +664,28 @@ object CaptureSet:
695664 assert(elem.subsumes(elem1),
696665 i " Skipped map ${tm.getClass} maps newly added $elem to $elem1 in $this" )
697666
667+ protected def includeElem (elem : Capability )(using Context ): Unit =
668+ if ! elems.contains(elem) then
669+ elems += elem
670+ TypeComparer .logUndoAction: () =>
671+ elems -= elem
672+
673+ def includeDep (cs : CaptureSet )(using Context ): Unit =
674+ if ! deps.contains(cs) then
675+ deps += cs
676+ TypeComparer .logUndoAction: () =>
677+ deps -= cs
678+
698679 final def addThisElem (elem : Capability )(using Context , VarState ): Boolean =
699- if isConst || ! recordElemsState() then // Fail if variable is solved or given VarState is frozen
680+ if isConst || ! varState.canRecord then // Fail if variable is solved or given VarState is frozen
700681 addIfHiddenOrFail(elem)
701682 else if ! levelOK(elem) then
702683 failWith(IncludeFailure (this , elem, levelError = true )) // or `elem` is not visible at the level of the set.
703684 else
704685 // id == 108 then assert(false, i"trying to add $elem to $this")
705686 assert(elem.isWellformed, elem)
706687 assert(! this .isInstanceOf [HiddenSet ] || summon[VarState ].isSeparating, summon[VarState ])
707- elems += elem
688+ includeElem( elem)
708689 if isBadRoot(rootLimit, elem) then
709690 rootAddedHandler()
710691 newElemAddedHandler(elem)
@@ -772,7 +753,7 @@ object CaptureSet:
772753 (cs eq this )
773754 || cs.isUniversal
774755 || isConst
775- || recordDepsState() && { deps += cs ; true }
756+ || varState.canRecord && { includeDep(cs) ; true }
776757
777758 override def disallowRootCapability (upto : Symbol )(handler : () => Context ?=> Unit )(using Context ): this .type =
778759 rootLimit = upto
@@ -1126,7 +1107,7 @@ object CaptureSet:
11261107 if alias ne this then alias.add(elem)
11271108 else
11281109 def addToElems () =
1129- elems += elem
1110+ includeElem( elem)
11301111 deps.foreach: dep =>
11311112 assert(dep != this )
11321113 vs.addHidden(dep.asInstanceOf [HiddenSet ], elem)
@@ -1142,7 +1123,7 @@ object CaptureSet:
11421123 deps = SimpleIdentitySet (elem.hiddenSet)
11431124 else
11441125 addToElems()
1145- elem.hiddenSet.deps += this
1126+ elem.hiddenSet.includeDep( this )
11461127 case _ =>
11471128 addToElems()
11481129
@@ -1238,41 +1219,15 @@ object CaptureSet:
12381219 */
12391220 class VarState :
12401221
1241- /** A map from captureset variables to their elements at the time of the snapshot. */
1242- private val elemsMap : util.EqHashMap [Var , Refs ] = new util.EqHashMap
1243-
1244- /** A map from captureset variables to their dependent sets at the time of the snapshot. */
1245- private val depsMap : util.EqHashMap [Var , Deps ] = new util.EqHashMap
1246-
12471222 /** A map from ResultCap values to other ResultCap values. If two result values
12481223 * `a` and `b` are unified, then `eqResultMap(a) = b` and `eqResultMap(b) = a`.
12491224 */
12501225 private var eqResultMap : util.SimpleIdentityMap [ResultCap , ResultCap ] = util.SimpleIdentityMap .empty
12511226
1252- /** A snapshot of the `eqResultMap` value at the start of a VarState transaction */
1253- private var eqResultSnapshot : util.SimpleIdentityMap [ResultCap , ResultCap ] | Null = null
1254-
1255- /** The recorded elements of `v` (it's required that a recording was made) */
1256- def elems (v : Var ): Refs = elemsMap(v)
1257-
1258- /** Optionally the recorded elements of `v`, None if nothing was recorded for `v` */
1259- def getElems (v : Var ): Option [Refs ] = elemsMap.get(v)
1260-
12611227 /** Record elements, return whether this was allowed.
12621228 * By default, recording is allowed in regular but not in frozen states.
12631229 */
1264- def putElems (v : Var , elems : Refs ): Boolean = { elemsMap(v) = elems; true }
1265-
1266- /** The recorded dependent sets of `v` (it's required that a recording was made) */
1267- def deps (v : Var ): Deps = depsMap(v)
1268-
1269- /** Optionally the recorded dependent sets of `v`, None if nothing was recorded for `v` */
1270- def getDeps (v : Var ): Option [Deps ] = depsMap.get(v)
1271-
1272- /** Record dependent sets, return whether this was allowed.
1273- * By default, recording is allowed in regular but not in frozen states.
1274- */
1275- def putDeps (v : Var , deps : Deps ): Boolean = { depsMap(v) = deps; true }
1230+ def canRecord : Boolean = true
12761231
12771232 /** Does this state allow additions of elements to capture set variables? */
12781233 def isOpen = true
@@ -1283,11 +1238,6 @@ object CaptureSet:
12831238 * but the special state VarState.Separate overrides this.
12841239 */
12851240 def addHidden (hidden : HiddenSet , elem : Capability )(using Context ): Boolean =
1286- elemsMap.get(hidden) match
1287- case None =>
1288- elemsMap(hidden) = hidden.elems
1289- depsMap(hidden) = hidden.deps
1290- case _ =>
12911241 hidden.add(elem)(using ctx, this )
12921242 true
12931243
@@ -1311,17 +1261,13 @@ object CaptureSet:
13111261 && eqResultMap(c1) == null
13121262 && eqResultMap(c2) == null
13131263 && {
1314- if eqResultSnapshot == null then eqResultSnapshot = eqResultMap
13151264 eqResultMap = eqResultMap.updated(c1, c2).updated(c2, c1)
1265+ TypeComparer .logUndoAction: () =>
1266+ eqResultMap.remove(c1)
1267+ eqResultMap.remove(c2)
13161268 true
13171269 }
13181270
1319- /** Roll back global state to what was recorded in this VarState */
1320- def rollBack (): Unit =
1321- elemsMap.keysIterator.foreach(_.resetElems()(using this ))
1322- depsMap.keysIterator.foreach(_.resetDeps()(using this ))
1323- if eqResultSnapshot != null then eqResultMap = eqResultSnapshot.nn
1324-
13251271 private var seen : util.EqHashSet [Capability ] = new util.EqHashSet
13261272
13271273 /** Run test `pred` unless `ref` was seen in an enclosing `ifNotSeen` operation */
@@ -1341,8 +1287,7 @@ object CaptureSet:
13411287 * subsume arbitary types, which are then recorded in their hidden sets.
13421288 */
13431289 class Closed extends VarState :
1344- override def putElems (v : Var , refs : Refs ) = false
1345- override def putDeps (v : Var , deps : Deps ) = false
1290+ override def canRecord = false
13461291 override def isOpen = false
13471292 override def toString = " closed varState"
13481293
@@ -1366,23 +1311,29 @@ object CaptureSet:
13661311 */
13671312 def HardSeparate (using Context ): Separating = ccState.HardSeparate
13681313
1369- /** A special state that turns off recording of elements. Used only
1370- * in `addSub` to prevent cycles in recordings. Instantiated in ccState.Unrecorded.
1371- */
1372- class Unrecorded extends VarState :
1373- override def putElems (v : Var , refs : Refs ) = true
1374- override def putDeps (v : Var , deps : Deps ) = true
1375- override def rollBack (): Unit = ()
1314+ /** A mixin trait that overrides the addHidden and unify operations to
1315+ * not depend in state. */
1316+ trait Stateless extends VarState :
1317+
1318+ /** Allow adding hidden elements, but don't store them */
13761319 override def addHidden (hidden : HiddenSet , elem : Capability )(using Context ): Boolean = true
1320+
1321+ /** Don't allow to unify result caps */
1322+ override def unify (c1 : ResultCap , c2 : ResultCap )(using Context ): Boolean = false
1323+ end Stateless
1324+
1325+ /** An open state that turns off recording of hidden elements (but allows
1326+ * adding them). Used in `addAsDependentTo`. Instantiated in ccState.Unrecorded.
1327+ */
1328+ class Unrecorded extends VarState , Stateless :
13771329 override def toString = " unrecorded varState"
13781330
13791331 def Unrecorded (using Context ): Unrecorded = ccState.Unrecorded
13801332
13811333 /** A closed state that turns off recording of hidden elements (but allows
13821334 * adding them). Used in `mightAccountFor`. Instantiated in ccState.ClosedUnrecorded.
13831335 */
1384- class ClosedUnrecorded extends Closed :
1385- override def addHidden (hidden : HiddenSet , elem : Capability )(using Context ): Boolean = true
1336+ class ClosedUnrecorded extends Closed , Stateless :
13861337 override def toString = " closed unrecorded varState"
13871338
13881339 def ClosedUnrecorded (using Context ): ClosedUnrecorded = ccState.ClosedUnrecorded
0 commit comments