@@ -13,6 +13,7 @@ import CCState.*
1313import Periods .NoRunId
1414import compiletime .uninitialized
1515import 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.
@@ -78,15 +79,24 @@ trait CaptureRef extends TypeProxy, ValueType:
7879 case tp : TermRef => tp.name == nme.CAPTURE_ROOT && tp.symbol == defn.captureRoot
7980 case _ => false
8081
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+
8190 /** Is this reference one the generic root capabilities `cap` or `cap.rd` ? */
8291 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
8594
8695 /** Is this reference capability that does not derive from another capability ? */
8796 final def isMaxCapability (using Context ): Boolean = this match
8897 case tp : TermRef => tp.isCap || tp.info.derivesFrom(defn.Caps_Exists )
8998 case tp : TermParamRef => tp.underlying.derivesFrom(defn.Caps_Exists )
99+ case Fresh .Cap (_) => true
90100 case ReadOnlyCapability (tp1) => tp1.isMaxCapability
91101 case _ => false
92102
@@ -137,34 +147,36 @@ trait CaptureRef extends TypeProxy, ValueType:
137147 * Y: CapSet^c1...CapSet^c2, x subsumes (CapSet^c2) ==> x subsumes Y
138148 * Contains[X, y] ==> X subsumes y
139149 *
140- * TODO: Document cases with more comments.
150+ * TODO: Move to CaptureSet
141151 */
142- final def subsumes (y : CaptureRef )(using Context ): Boolean =
152+ final def subsumes (y : CaptureRef )(using ctx : Context , vs : VarState = VarState .Separate ): Boolean =
153+
143154 def subsumingRefs (x : Type , y : Type ): Boolean = x match
144155 case x : CaptureRef => y match
145156 case y : CaptureRef => x.subsumes(y)
146157 case _ => false
147158 case _ => false
148159
149- def viaInfo (info : Type )(test : Type => Boolean ): Boolean = info.match
160+ def viaInfo (info : Type )(test : Type => Boolean ): Boolean = info.dealias match
150161 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)
151172 case info : AndType => viaInfo(info.tp1)(test) || viaInfo(info.tp2)(test)
152173 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)
162174 case _ => false
163175
164176 (this eq y)
165- || this .isCap
177+ || maxSubsumes(y, canAddHidden = ! vs.isOpen)
166178 || y.match
167- case y : TermRef if ! y.isRootCapability =>
179+ case y : TermRef if ! y.isCap =>
168180 y.prefix.match
169181 case ypre : CaptureRef =>
170182 this .subsumes(ypre)
@@ -213,6 +225,27 @@ trait CaptureRef extends TypeProxy, ValueType:
213225 case _ => false
214226 end subsumes
215227
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+
216249 def assumedContainsOf (x : TypeRef )(using Context ): SimpleIdentitySet [CaptureRef ] =
217250 CaptureSet .assumedContains.getOrElse(x, SimpleIdentitySet .empty)
218251
0 commit comments