@@ -13,6 +13,7 @@ import CCState.*
13
13
import Periods .NoRunId
14
14
import compiletime .uninitialized
15
15
import StdNames .nme
16
+ import CaptureSet .VarState
16
17
17
18
/** A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs,
18
19
* as well as three kinds of AnnotatedTypes representing readOnly, reach, and maybe capabilities.
@@ -78,15 +79,24 @@ trait CaptureRef extends TypeProxy, ValueType:
78
79
case tp : TermRef => tp.name == nme.CAPTURE_ROOT && tp.symbol == defn.captureRoot
79
80
case _ => false
80
81
82
+ /** Is this reference a Fresh.Cap instance? */
83
+ final def isFresh (using Context ): Boolean = this match
84
+ case Fresh .Cap (_) => true
85
+ case _ => false
86
+
87
+ /** Is this reference the generic root capability `cap` or a Fresh.Cap instance? */
88
+ final def isCapOrFresh (using Context ): Boolean = isCap || isFresh
89
+
81
90
/** Is this reference one the generic root capabilities `cap` or `cap.rd` ? */
82
91
final def isRootCapability (using Context ): Boolean = this match
83
- case ReadOnlyCapability (tp1) => tp1.isCap
84
- case _ => isCap
92
+ case ReadOnlyCapability (tp1) => tp1.isCapOrFresh
93
+ case _ => isCapOrFresh
85
94
86
95
/** Is this reference capability that does not derive from another capability ? */
87
96
final def isMaxCapability (using Context ): Boolean = this match
88
97
case tp : TermRef => tp.isCap || tp.info.derivesFrom(defn.Caps_Exists )
89
98
case tp : TermParamRef => tp.underlying.derivesFrom(defn.Caps_Exists )
99
+ case Fresh .Cap (_) => true
90
100
case ReadOnlyCapability (tp1) => tp1.isMaxCapability
91
101
case _ => false
92
102
@@ -137,34 +147,36 @@ trait CaptureRef extends TypeProxy, ValueType:
137
147
* Y: CapSet^c1...CapSet^c2, x subsumes (CapSet^c2) ==> x subsumes Y
138
148
* Contains[X, y] ==> X subsumes y
139
149
*
140
- * TODO: Document cases with more comments.
150
+ * TODO: Move to CaptureSet
141
151
*/
142
- final def subsumes (y : CaptureRef )(using Context ): Boolean =
152
+ final def subsumes (y : CaptureRef )(using ctx : Context , vs : VarState = VarState .Separate ): Boolean =
153
+
143
154
def subsumingRefs (x : Type , y : Type ): Boolean = x match
144
155
case x : CaptureRef => y match
145
156
case y : CaptureRef => x.subsumes(y)
146
157
case _ => false
147
158
case _ => false
148
159
149
- def viaInfo (info : Type )(test : Type => Boolean ): Boolean = info.match
160
+ def viaInfo (info : Type )(test : Type => Boolean ): Boolean = info.dealias match
150
161
case info : SingletonCaptureRef => test(info)
162
+ case CapturingType (parent, _) =>
163
+ if this .derivesFrom(defn.Caps_CapSet ) then test(info)
164
+ /*
165
+ If `this` is a capture set variable `C^`, then it is possible that it can be
166
+ reached from term variables in a reachability chain through the context.
167
+ For instance, in `def test[C^](src: Foo^{C^}) = { val x: Foo^{src} = src; val y: Foo^{x} = x; y }`
168
+ we expect that `C^` subsumes `x` and `y` in the body of the method
169
+ (cf. test case cc-poly-varargs.scala for a more involved example).
170
+ */
171
+ else viaInfo(parent)(test)
151
172
case info : AndType => viaInfo(info.tp1)(test) || viaInfo(info.tp2)(test)
152
173
case info : OrType => viaInfo(info.tp1)(test) && viaInfo(info.tp2)(test)
153
- case info @ CapturingType (_,_) if this .derivesFrom(defn.Caps_CapSet ) =>
154
- /*
155
- If `this` is a capture set variable `C^`, then it is possible that it can be
156
- reached from term variables in a reachability chain through the context.
157
- For instance, in `def test[C^](src: Foo^{C^}) = { val x: Foo^{src} = src; val y: Foo^{x} = x; y }`
158
- we expect that `C^` subsumes `x` and `y` in the body of the method
159
- (cf. test case cc-poly-varargs.scala for a more involved example).
160
- */
161
- test(info)
162
174
case _ => false
163
175
164
176
(this eq y)
165
- || this .isCap
177
+ || maxSubsumes(y, canAddHidden = ! vs.isOpen)
166
178
|| y.match
167
- case y : TermRef if ! y.isRootCapability =>
179
+ case y : TermRef if ! y.isCap =>
168
180
y.prefix.match
169
181
case ypre : CaptureRef =>
170
182
this .subsumes(ypre)
@@ -213,6 +225,27 @@ trait CaptureRef extends TypeProxy, ValueType:
213
225
case _ => false
214
226
end subsumes
215
227
228
+ /** This is a maximal capabaility that subsumes `y` in given context and VarState.
229
+ * @param canAddHidden If true we allow maximal capabilties to subsume all other capabilities.
230
+ * We add those capabilities to the hidden set if this is Fresh.Cap
231
+ * If false we only accept `y` elements that are already in the
232
+ * hidden set of this Fresh.Cap. The idea is that in a VarState that
233
+ * accepts additions we first run `maxSubsumes` with `canAddHidden = false`
234
+ * so that new variables get added to the sets. If that fails, we run
235
+ * the test again with canAddHidden = true as a last effort before we
236
+ * fail a comparison.
237
+ */
238
+ def maxSubsumes (y : CaptureRef , canAddHidden : Boolean )(using ctx : Context , vs : VarState = VarState .Separate ): Boolean =
239
+ this .match
240
+ case Fresh .Cap (hidden) =>
241
+ vs.ifNotSeen(this )(hidden.elems.exists(_.subsumes(y)))
242
+ || ! y.stripReadOnly.isCap && canAddHidden && vs.addHidden(hidden, y)
243
+ case _ =>
244
+ this .isCap && canAddHidden
245
+ || y.match
246
+ case ReadOnlyCapability (y1) => this .stripReadOnly.maxSubsumes(y1, canAddHidden)
247
+ case _ => false
248
+
216
249
def assumedContainsOf (x : TypeRef )(using Context ): SimpleIdentitySet [CaptureRef ] =
217
250
CaptureSet .assumedContains.getOrElse(x, SimpleIdentitySet .empty)
218
251
0 commit comments