@@ -320,18 +320,27 @@ extension (tp: Type)
320
320
/** The capture set consisting of all top-level captures of `tp` that appear under a box.
321
321
* Unlike for `boxed` this also considers parents of capture types, unions and
322
322
* intersections, and type proxies other than abstract types.
323
+ * Furthermore, if the original type is a capture ref `x`, it replaces boxed universal sets
324
+ * on the fly with x*.
323
325
*/
324
326
def boxedCaptureSet (using Context ): CaptureSet =
325
- def getBoxed (tp : Type ): CaptureSet = tp match
327
+ def getBoxed (tp : Type , pre : Type ): CaptureSet = tp match
326
328
case tp @ CapturingType (parent, refs) =>
327
- val pcs = getBoxed(parent)
328
- if tp.isBoxed then refs ++ pcs else pcs
329
+ val pcs = getBoxed(parent, pre)
330
+ if ! tp.isBoxed then
331
+ pcs
332
+ else if pre.exists && refs.containsRootCapability then
333
+ val reachRef = if refs.isReadOnly then pre.reach.readOnly else pre.reach
334
+ pcs ++ reachRef.singletonCaptureSet
335
+ else
336
+ pcs ++ refs
337
+ case ref : CaptureRef if ref.isTracked && ! pre.exists => getBoxed(ref, ref)
329
338
case tp : TypeRef if tp.symbol.isAbstractOrParamType => CaptureSet .empty
330
- case tp : TypeProxy => getBoxed(tp.superType)
331
- case tp : AndType => getBoxed(tp.tp1) ** getBoxed(tp.tp2)
332
- case tp : OrType => getBoxed(tp.tp1) ++ getBoxed(tp.tp2)
339
+ case tp : TypeProxy => getBoxed(tp.superType, pre )
340
+ case tp : AndType => getBoxed(tp.tp1, pre ) ** getBoxed(tp.tp2, pre )
341
+ case tp : OrType => getBoxed(tp.tp1, pre ) ++ getBoxed(tp.tp2, pre )
333
342
case _ => CaptureSet .empty
334
- getBoxed(tp)
343
+ getBoxed(tp, NoType )
335
344
336
345
/** Is the boxedCaptureSet of this type nonempty? */
337
346
def isBoxedCapturing (using Context ): Boolean =
0 commit comments