@@ -38,7 +38,7 @@ sealed abstract class CaptureSet extends Showable:
38
38
* in all their supersets.
39
39
* @return true iff elements were added
40
40
*/
41
- protected def addNewElems (newElems : Refs )(using Context ): Boolean
41
+ protected def addNewElems (newElems : Refs )(using Context , VarState ): Boolean
42
42
43
43
/** If this is a variable, add `cs` as a super set */
44
44
protected def addSuper (cs : CaptureSet ): this .type
@@ -52,17 +52,25 @@ sealed abstract class CaptureSet extends Showable:
52
52
* capture set. Inclusion is via `addElems`.
53
53
* @return true iff elements were added
54
54
*/
55
- protected def tryInclude (elems : Refs )(using Context ): Boolean =
55
+ protected def tryInclude (elems : Refs )(using Context , VarState ): Boolean =
56
56
val unaccounted = elems.filter(! accountsFor(_))
57
57
unaccounted.isEmpty || addNewElems(unaccounted)
58
58
59
- /** {x} <:< this where <:< is subcapturing */
59
+ /** {x} <:< this where <:< is subcapturing, but treating all variables
60
+ * as frozen.
61
+ */
60
62
def accountsFor (x : CaptureRef )(using Context ) =
61
63
elems.contains(x) || ! x.isRootCapability && x.captureSetOfInfo <:< this
62
64
63
65
/** The subcapturing test */
64
66
def <:< (that : CaptureSet )(using Context ): Boolean =
65
- that.tryInclude(elems) && { addSuper(that); true }
67
+ given VarState = new VarState
68
+ val result = that.tryInclude(elems)
69
+ if result then addSuper(that) else abort()
70
+ result
71
+
72
+ private def abort ()(using state : VarState ): Unit =
73
+ state.keysIterator.foreach(_.reset())
66
74
67
75
/** The smallest capture set (via <:<) that is a superset of both
68
76
* `this` and `that`
@@ -134,7 +142,7 @@ object CaptureSet:
134
142
def isConst = true
135
143
def isEmpty : Boolean = elems.isEmpty
136
144
137
- def addNewElems (elems : Refs )(using Context ): Boolean = false
145
+ def addNewElems (elems : Refs )(using Context , VarState ): Boolean = false
138
146
def addSuper (cs : CaptureSet ) = this
139
147
140
148
override def toString = elems.toString
@@ -150,8 +158,20 @@ object CaptureSet:
150
158
def isConst = false
151
159
def isEmpty = false
152
160
153
- def addNewElems (newElems : Refs )(using Context ): Boolean =
154
- deps.forall(_.tryInclude(newElems)) && { elems ++= newElems; true }
161
+ private def recordState ()(using VarState ) = varState.get(this ) match
162
+ case None => varState(this ) = elems
163
+ case _ =>
164
+
165
+ def reset ()(using state : VarState ): Unit =
166
+ elems = state(this )
167
+
168
+ def addNewElems (newElems : Refs )(using Context , VarState ): Boolean =
169
+ deps.forall(_.tryInclude(newElems))
170
+ && {
171
+ recordState()
172
+ elems ++= newElems
173
+ true
174
+ }
155
175
156
176
def addSuper (cs : CaptureSet ) = { deps += cs; this }
157
177
@@ -164,12 +184,16 @@ object CaptureSet:
164
184
override def accountsFor (x : CaptureRef )(using Context ): Boolean =
165
185
f(x).elems.forall(super .accountsFor)
166
186
167
- override def addNewElems (newElems : Refs )(using Context ): Boolean =
187
+ override def addNewElems (newElems : Refs )(using Context , VarState ): Boolean =
168
188
super .addNewElems(mapRefs(newElems, f).elems)
169
189
170
190
override def toString = s " Mapped $id$elems"
171
191
end Mapped
172
192
193
+ type VarState = util.EqHashMap [Var , Refs ]
194
+
195
+ def varState (using state : VarState ): VarState = state
196
+
173
197
def mapRefs (xs : Refs , f : CaptureRef => CaptureSet )(using Context ): CaptureSet =
174
198
(empty /: xs)((cs, x) => cs ++ f(x))
175
199
0 commit comments