@@ -210,10 +210,11 @@ sealed abstract class CaptureSet extends Showable:
210210 * any of the elements in the constant capture set `that`
211211 */
212212 def -- (that : CaptureSet .Const )(using Context ): CaptureSet =
213- val elems1 = elems.filter(! that.accountsFor(_))
214- if elems1.size == elems.size then this
215- else if this .isConst then Const (elems1)
216- else Diff (asVar, that)
213+ if this .isConst then
214+ val elems1 = elems.filter(! that.accountsFor(_))
215+ if elems1.size == elems.size then this else Const (elems1)
216+ else
217+ if that.isAlwaysEmpty then this else Diff (asVar, that)
217218
218219 /** The largest subset (via <:<) of this capture set that does not account for `ref` */
219220 def - (ref : CaptureRef )(using Context ): CaptureSet =
@@ -845,34 +846,45 @@ object CaptureSet:
845846 /** The capture set of the type underlying a CaptureRef */
846847 def ofInfo (ref : CaptureRef )(using Context ): CaptureSet = ref match
847848 case ref : TermRef if ref.isRootCapability => ref.singletonCaptureSet
848- case _ => ofType(ref.underlying)
849+ case _ => ofType(ref.underlying, followResult = true )
849850
850851 /** Capture set of a type */
851- def ofType (tp : Type )(using Context ): CaptureSet =
852- def recur (tp : Type ): CaptureSet = tp.dealias match
853- case tp : TermRef =>
854- tp.captureSet
855- case tp : TermParamRef =>
856- tp.captureSet
857- case _ : TypeRef =>
858- if tp.classSymbol.hasAnnotation(defn.CapabilityAnnot ) then universal else empty
859- case _ : TypeParamRef =>
860- empty
861- case CapturingType (parent, refs) =>
862- recur(parent) ++ refs
863- case AppliedType (tycon, args) =>
864- val cs = recur(tycon)
865- tycon.typeParams match
866- case tparams @ (LambdaParam (tl, _) :: _) => cs.substParams(tl, args)
867- case _ => cs
868- case tp : TypeProxy =>
869- recur(tp.underlying)
870- case AndType (tp1, tp2) =>
871- recur(tp1) ** recur(tp2)
872- case OrType (tp1, tp2) =>
873- recur(tp1) ++ recur(tp2)
874- case _ =>
875- empty
852+ def ofType (tp : Type , followResult : Boolean )(using Context ): CaptureSet =
853+ def recur (tp : Type ): CaptureSet = trace(i " ofType $tp, ${tp.getClass} $followResult" , show = true ):
854+ tp.dealias match
855+ case tp : TermRef =>
856+ tp.captureSet
857+ case tp : TermParamRef =>
858+ tp.captureSet
859+ case _ : TypeRef =>
860+ if tp.classSymbol.hasAnnotation(defn.CapabilityAnnot ) then universal else empty
861+ case _ : TypeParamRef =>
862+ empty
863+ case CapturingType (parent, refs) =>
864+ recur(parent) ++ refs
865+ case tpd @ RefinedType (parent, _, rinfo : MethodType )
866+ if followResult && defn.isFunctionType(tpd) =>
867+ ofType(parent, followResult = false ) // pick up capture set from parent type
868+ ++ (recur(rinfo.resType) // add capture set of result
869+ -- CaptureSet (rinfo.paramRefs.filter(_.isTracked)* )) // but disregard bound parameters
870+ case tpd @ AppliedType (tycon, args) =>
871+ if followResult && defn.isNonRefinedFunction(tpd) then
872+ recur(args.last)
873+ // must be (pure) FunctionN type since ImpureFunctions have already
874+ // been eliminated in selector's dealias. Use capture set of result.
875+ else
876+ val cs = recur(tycon)
877+ tycon.typeParams match
878+ case tparams @ (LambdaParam (tl, _) :: _) => cs.substParams(tl, args)
879+ case _ => cs
880+ case tp : TypeProxy =>
881+ recur(tp.underlying)
882+ case AndType (tp1, tp2) =>
883+ recur(tp1) ** recur(tp2)
884+ case OrType (tp1, tp2) =>
885+ recur(tp1) ++ recur(tp2)
886+ case _ =>
887+ empty
876888 recur(tp)
877889 .showing(i " capture set of $tp = $result" , capt)
878890
0 commit comments