@@ -210,10 +210,11 @@ sealed abstract class CaptureSet extends Showable:
210
210
* any of the elements in the constant capture set `that`
211
211
*/
212
212
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)
217
218
218
219
/** The largest subset (via <:<) of this capture set that does not account for `ref` */
219
220
def - (ref : CaptureRef )(using Context ): CaptureSet =
@@ -845,34 +846,45 @@ object CaptureSet:
845
846
/** The capture set of the type underlying a CaptureRef */
846
847
def ofInfo (ref : CaptureRef )(using Context ): CaptureSet = ref match
847
848
case ref : TermRef if ref.isRootCapability => ref.singletonCaptureSet
848
- case _ => ofType(ref.underlying)
849
+ case _ => ofType(ref.underlying, followResult = true )
849
850
850
851
/** 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
876
888
recur(tp)
877
889
.showing(i " capture set of $tp = $result" , capt)
878
890
0 commit comments