Skip to content

Commit ca19b46

Browse files
authored
Change handling of curried function types in capture checking (#18131)
Implements the proposed treatment in cc-paths. - Capture sets of curried functions don't automatically propagate to the left - When computing the capture set of a reference, pick up capture sets along the span of curried functions - Drop the previous syntactic sugar for propagating captures left to right in curried function types.
2 parents 04eae14 + c7a5350 commit ca19b46

15 files changed

+304
-307
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

+42-30
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)