Skip to content

Commit

Permalink
Refacture and document CaputureSet
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Jan 10, 2025
1 parent f7788e4 commit 84bf872
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 19 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/CaptureOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ abstract class AnnotatedCapability(annot: Context ?=> ClassSymbol):
case _ =>
AnnotatedType(tp, Annotation(annot, util.Spans.NoSpan))
def unapply(tree: AnnotatedType)(using Context): Option[CaptureRef] = tree match
case AnnotatedType(parent: CaptureRef, ann) if ann.symbol == annot => Some(parent)
case AnnotatedType(parent: CaptureRef, ann) if ann.hasSymbol(annot) => Some(parent)
case _ => None
protected def unwrappable(using Context): Set[Symbol]

Expand Down
30 changes: 12 additions & 18 deletions compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -185,21 +185,13 @@ sealed abstract class CaptureSet extends Showable:
*/
def accountsFor(x: CaptureRef)(using ctx: Context, vs: VarState = VarState.Separate): Boolean =

/** Like `refs.exists(p)`, but testing fresh cap instances in refs last */
def existsElem(refs: SimpleIdentitySet[CaptureRef], p: CaptureRef => Boolean): Boolean =
refs.exists:
case Fresh.Cap(_) => false
case elem => p(elem)
||
refs.exists:
case elem @ Fresh.Cap(_) => p(elem)
case elem => false

def debugInfo(using Context) = i"$this accountsFor $x, which has capture set ${x.captureSetOfInfo}"

def test(using Context) = reporting.trace(debugInfo):
existsElem(elems, _.subsumes(x))
|| !x.isMaxCapability
elems.exists(_.subsumes(x))
|| // Even though subsumes already follows captureSetOfInfo, this is not enough.
// For instance x: C^{y, z}. Then neither y nor z subsumes x but {y, z} accounts for x.
!x.isMaxCapability
&& !x.derivesFrom(defn.Caps_CapSet)
&& !(vs == VarState.Separate && x.captureSetOfInfo.containsRootCapability)
// in VarState.Separate, don't try to widen to cap since that might succeed with {cap} <: {cap}
Expand Down Expand Up @@ -244,7 +236,7 @@ sealed abstract class CaptureSet extends Showable:
subCaptures(that)(using ctx, vs)

/** The subcapturing test, using a given VarState */
def subCaptures(that: CaptureSet)(using ctx: Context, vs: VarState = VarState()): CompareResult =
final def subCaptures(that: CaptureSet)(using ctx: Context, vs: VarState = VarState()): CompareResult =
val result = that.tryInclude(elems, this)
if result.isOK then
addDependent(that)
Expand Down Expand Up @@ -543,7 +535,7 @@ object CaptureSet:
deps = state.deps(this)

final def addThisElem(elem: CaptureRef)(using Context, VarState): CompareResult =
if isConst || !recordElemsState() then // Fail if variable is solved or given VarState is frozen
if isConst || !recordElemsState() then // Fail if variable is solved or given VarState is frozen
addHiddenElem(elem)
else if Existential.isBadExistential(elem) then // Fail if `elem` is an out-of-scope existential
CompareResult.Fail(this :: Nil)
Expand Down Expand Up @@ -1210,13 +1202,15 @@ object CaptureSet:
tp.captureSet
case tp: TermParamRef =>
tp.captureSet
case _: TypeRef =>
empty
case _: TypeParamRef =>
empty
case tp: (TypeRef | TypeParamRef) =>
if tp.derivesFrom(defn.Caps_CapSet) then tp.captureSet
else empty
case CapturingType(parent, refs) =>
recur(parent) ++ refs
case tp @ AnnotatedType(parent, ann) if ann.hasSymbol(defn.ReachCapabilityAnnot) =>
// Note: we don't use the `ReachCapability(parent)` extractor here since that
// only works if `parent` is a CaptureRef, but in illegal programs it might not be.
// And then we do not want to fall back to empty.
parent match
case parent: SingletonCaptureRef if parent.isTrackableRef =>
tp.singletonCaptureSet
Expand Down

0 comments on commit 84bf872

Please sign in to comment.