@@ -222,19 +222,27 @@ extension (tp: Type)
222222    case  tp : SingletonCaptureRef  =>  tp.captureSetOfInfo
223223    case  _ =>  CaptureSet .ofType(tp, followResult =  false )
224224
225-   /**  The deep capture set of a type. 
226-    *  For singleton capabilities `x` and reach capabilities `x*`, this is `{x*}`, provided 
227-    *  the underlying capture set resulting from traversing the type is non-empty. 
228-    *  For other types this is the union of all covariant capture sets embedded 
229-    *  in the type, as computed by `CaptureSet.ofTypeDeeply`. 
225+   /**  The deep capture set of a type. This is by default the union of all 
226+    *  covariant capture sets embedded in the widened type, as computed by 
227+    *  `CaptureSet.ofTypeDeeply`. If that set is nonempty, and the type is 
228+    *  a singleton capability `x` or a reach capability `x*`, the deep capture 
229+    *  set can be narrowed to`{x*}`. However, A deep capture set should not be 
230+    *  narrowed to a reach capability `x*` if there are elements in the underlying 
231+    *  set that live longer than `x`. See `delayedRunops.scala` for a test case. 
230232   */  
231233  def  deepCaptureSet (using  Context ):  CaptureSet  = 
232234    val  dcs  =  CaptureSet .ofTypeDeeply(tp.widen.stripCapturing)
235+     def  reachCanSubsumDcs  = 
236+       dcs.isUniversal
237+       ||  dcs.elems.forall(c =>  c.pathOwner.isContainedIn(tp.pathOwner))
233238    if  dcs.isAlwaysEmpty then  tp.captureSet
234239    else  tp match 
235-       case  tp @  ReachCapability (_) =>  tp.singletonCaptureSet
236-       case  tp : SingletonCaptureRef  if  tp.isTrackableRef =>  tp.reach.singletonCaptureSet
237-       case  _ =>  tp.captureSet ++  dcs
240+       case  tp @  ReachCapability (_) if  reachCanSubsumDcs => 
241+         tp.singletonCaptureSet
242+       case  tp : SingletonCaptureRef  if  tp.isTrackableRef &&  reachCanSubsumDcs => 
243+         tp.reach.singletonCaptureSet
244+       case  _ => 
245+         tp.captureSet ++  dcs
238246
239247  /**  A type capturing `ref` */  
240248  def  capturing (ref : CaptureRef )(using  Context ):  Type  = 
@@ -277,8 +285,18 @@ extension (tp: Type)
277285  /**  The first element of this path type */  
278286  final  def  pathRoot (using  Context ):  Type  =  tp.dealias match 
279287    case  tp1 : NamedType  if  tp1.symbol.owner.isClass =>  tp1.prefix.pathRoot
288+     case  tp1 @  ReachCapability (tp2) =>  tp2.pathRoot
280289    case  _ =>  tp
281290
291+   /**  If this part starts with `C.this`, the class `C`. 
292+    *  Otherwise, if it starts with a reference `r`, `r`'s owner. 
293+    *  Otherwise NoSymbol. 
294+    */  
295+   final  def  pathOwner (using  Context ):  Symbol  =  pathRoot match 
296+     case  tp1 : NamedType  =>  tp1.symbol.owner
297+     case  tp1 : ThisType  =>  tp1.cls
298+     case  _ =>  NoSymbol 
299+ 
282300  /**  If this is a unboxed capturing type with nonempty capture set, its boxed version. 
283301   *  Or, if type is a TypeBounds of capturing types, the version where the bounds are boxed. 
284302   *  The identity for all other types. 
0 commit comments