Skip to content

Commit 9c96538

Browse files
committed
Follow span of function types when computing captureSetOfInfo
1 parent d07282d commit 9c96538

File tree

4 files changed

+45
-28
lines changed

4 files changed

+45
-28
lines changed

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

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -846,34 +846,45 @@ object CaptureSet:
846846
/** The capture set of the type underlying a CaptureRef */
847847
def ofInfo(ref: CaptureRef)(using Context): CaptureSet = ref match
848848
case ref: TermRef if ref.isRootCapability => ref.singletonCaptureSet
849-
case _ => ofType(ref.underlying)
849+
case _ => ofType(ref.underlying, followResult = true)
850850

851851
/** Capture set of a type */
852-
def ofType(tp: Type)(using Context): CaptureSet =
853-
def recur(tp: Type): CaptureSet = tp.dealias match
854-
case tp: TermRef =>
855-
tp.captureSet
856-
case tp: TermParamRef =>
857-
tp.captureSet
858-
case _: TypeRef =>
859-
if tp.classSymbol.hasAnnotation(defn.CapabilityAnnot) then universal else empty
860-
case _: TypeParamRef =>
861-
empty
862-
case CapturingType(parent, refs) =>
863-
recur(parent) ++ refs
864-
case AppliedType(tycon, args) =>
865-
val cs = recur(tycon)
866-
tycon.typeParams match
867-
case tparams @ (LambdaParam(tl, _) :: _) => cs.substParams(tl, args)
868-
case _ => cs
869-
case tp: TypeProxy =>
870-
recur(tp.underlying)
871-
case AndType(tp1, tp2) =>
872-
recur(tp1) ** recur(tp2)
873-
case OrType(tp1, tp2) =>
874-
recur(tp1) ++ recur(tp2)
875-
case _ =>
876-
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
877888
recur(tp)
878889
.showing(i"capture set of $tp = $result", capt)
879890

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,9 @@ class CheckCaptures extends Recheck, SymTransformer:
854854
actual match
855855
case ref: CaptureRef if ref.isTracked =>
856856
actualw match
857-
case CapturingType(p, refs) =>
857+
case CapturingType(p, refs) if ref.singletonCaptureSet.mightSubcapture(refs) =>
858858
actualw = actualw.derivedCapturingType(p, ref.singletonCaptureSet)
859+
.showing(i"improve $actualw to $result", capt)
859860
// given `a: C T`, improve `C T` to `{a} T`
860861
case _ =>
861862
case _ =>

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,7 @@ object Types {
15611561
}
15621562

15631563
/** The capture set of this type. Overridden and cached in CaptureRef */
1564-
def captureSet(using Context): CaptureSet = CaptureSet.ofType(this)
1564+
def captureSet(using Context): CaptureSet = CaptureSet.ofType(this, followResult = false)
15651565

15661566
// ----- Normalizing typerefs over refined types ----------------------------
15671567

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import language.experimental.captureChecking
2+
class ContextCls
3+
type Context = ContextCls^
4+
5+
class Filtered(p: (c: Context) ?-> () ->{c} Boolean) extends Pure

0 commit comments

Comments
 (0)