Skip to content

Commit

Permalink
Address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Feb 7, 2025
1 parent d684f60 commit 071bf19
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 32 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/cc/CaptureOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ extension (tp: Type)
case _ =>
ReadOnlyCapability(tp)

/** If `x` is a capture ref, replacxe all no-flip covariant occurrences of `cap`
/** If `x` is a capture ref, replace all no-flip covariant occurrences of `cap`
* in type `tp` with `x*`.
*/
def withReachCaptures(ref: Type)(using Context): Type =
Expand Down Expand Up @@ -758,7 +758,7 @@ object MaybeCapability extends AnnotatedCapability(defn.MaybeCapabilityAnnot):
protected def unwrappable(using Context) = Set()

/** An extractor for `ref @readOnlyCapability`, which is used to express
* the rad-only capability `ref.rd` as a type.
* the read-only capability `ref.rd` as a type.
*/
object ReadOnlyCapability extends AnnotatedCapability(defn.ReadOnlyCapabilityAnnot):
protected def unwrappable(using Context) = Set(defn.MaybeCapabilityAnnot)
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/cc/CaptureRef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ trait CaptureRef extends TypeProxy, ValueType:
case _ => false

/** An exclusive capability is a capability that derives
* indirectly from a maximal capability without goinh through
* indirectly from a maximal capability without going through
* a read-only capability first.
*/
final def isExclusive(using Context): Boolean =
!isReadOnly && (isMaxCapability || captureSetOfInfo.isExclusive)

// With the support of pathes, we don't need to normalize the `TermRef`s anymore.
// With the support of paths, we don't need to normalize the `TermRef`s anymore.
// /** Normalize reference so that it can be compared with `eq` for equality */
// final def normalizedRef(using Context): CaptureRef = this match
// case tp @ AnnotatedType(parent: CaptureRef, annot) if tp.isTrackableRef =>
Expand Down Expand Up @@ -242,7 +242,7 @@ trait CaptureRef extends TypeProxy, ValueType:
case _ => false
end subsumes

/** This is a maximal capabaility that subsumes `y` in given context and VarState.
/** This is a maximal capability that subsumes `y` in given context and VarState.
* @param canAddHidden If true we allow maximal capabilities to subsume all other capabilities.
* We add those capabilities to the hidden set if this is Fresh.Cap
* If false we only accept `y` elements that are already in the
Expand Down
24 changes: 10 additions & 14 deletions compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,7 @@ sealed abstract class CaptureSet extends Showable:
elems.forall(that.mightAccountFor)
&& !that.elems.forall(this.mightAccountFor)

/** The subcapturing test.
* @param frozen if true, no new variables or dependent sets are allowed to
* be added when making this test. An attempt to add either
* will result in failure.
*/
/** The subcapturing test, taking an explicit VarState. */
final def subCaptures(that: CaptureSet, vs: VarState)(using Context): CompareResult =
subCaptures(that)(using ctx, vs)

Expand Down Expand Up @@ -392,7 +388,7 @@ sealed abstract class CaptureSet extends Showable:
override def toText(printer: Printer): Text =
printer.toTextCaptureSet(this) ~~ description

/** Apply function `f` to the elements. Typcially used for printing.
/** Apply function `f` to the elements. Typically used for printing.
* Overridden in HiddenSet so that we don't run into infinite recursions
*/
def processElems[T](f: Refs => T): T = f(elems)
Expand All @@ -407,10 +403,10 @@ object CaptureSet:
/** If set to `true`, capture stack traces that tell us where sets are created */
private final val debugSets = false

val emptySet = SimpleIdentitySet.empty
val emptyRefs: Refs = SimpleIdentitySet.empty

/** The empty capture set `{}` */
val empty: CaptureSet.Const = Const(emptySet)
val empty: CaptureSet.Const = Const(emptyRefs)

/** The universal capture set `{cap}` */
def universal(using Context): CaptureSet =
Expand Down Expand Up @@ -466,7 +462,7 @@ object CaptureSet:
* nulls, this provides more lenient checking against compilation units that
* were not yet compiled with capture checking on.
*/
object Fluid extends Const(emptySet):
object Fluid extends Const(emptyRefs):
override def isAlwaysEmpty = false
override def addThisElem(elem: CaptureRef)(using Context, VarState) = CompareResult.OK
override def accountsFor(x: CaptureRef)(using Context, VarState): Boolean = true
Expand All @@ -475,7 +471,7 @@ object CaptureSet:
end Fluid

/** The subclass of captureset variables with given initial elements */
class Var(override val owner: Symbol = NoSymbol, initialElems: Refs = emptySet, val level: Level = undefinedLevel, underBox: Boolean = false)(using @constructorOnly ictx: Context) extends CaptureSet:
class Var(override val owner: Symbol = NoSymbol, initialElems: Refs = emptyRefs, val level: Level = undefinedLevel, underBox: Boolean = false)(using @constructorOnly ictx: Context) extends CaptureSet:

/** A unique identification number for diagnostics */
val id =
Expand All @@ -493,7 +489,7 @@ object CaptureSet:
/** The sets currently known to be dependent sets (i.e. new additions to this set
* are propagated to these dependent sets.)
*/
var deps: Deps = emptySet
var deps: Deps = SimpleIdentitySet.empty

def isConst = isSolved
def isAlwaysEmpty = isSolved && elems.isEmpty
Expand Down Expand Up @@ -927,16 +923,16 @@ object CaptureSet:
cs1.elems.filter(cs2.mightAccountFor) ++ cs2.elems.filter(cs1.mightAccountFor)

/** A capture set variable used to record the references hidden by a Fresh.Cap instance */
class HiddenSet(initialHidden: Refs = emptySet)(using @constructorOnly ictx: Context)
class HiddenSet(initialHidden: Refs = emptyRefs)(using @constructorOnly ictx: Context)
extends Var(initialElems = initialHidden):

/** Apply function `f` to `elems` while setting `elems` to empty for the
* duration. This is used to escape infinite recursions if two Frash.Caps
* duration. This is used to escape infinite recursions if two Fresh.Caps
* refer to each other in their hidden sets.
*/
override def processElems[T](f: Refs => T): T =
val savedElems = elems
elems = emptySet
elems = emptyRefs
try f(savedElems)
finally elems = savedElems
end HiddenSet
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ class CheckCaptures extends Recheck, SymTransformer:
case _ => denot

// Don't allow update methods to be called unless the qualifier captures
// contain an exclusive referenece. TODO This should probabkly rolled into
// an exclusive reference. TODO This should probably rolled into
// qualifier logic once we have it.
if tree.symbol.isUpdateMethod && !qualType.captureSet.isExclusive then
report.error(
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/cc/Fresh.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import NameKinds.ExistentialBinderName
import NameOps.isImpureFunction
import reporting.Message
import util.SimpleIdentitySet.empty
import CaptureSet.{Refs, emptySet, NarrowingCapabilityMap}
import CaptureSet.{Refs, emptyRefs, NarrowingCapabilityMap}
import dotty.tools.dotc.util.SimpleIdentitySet

/** A module for handling Fresh types. Fresh.Cap instances are top type that keep
Expand Down Expand Up @@ -43,14 +43,14 @@ object Fresh:
private def ownerToHidden(owner: Symbol, reach: Boolean)(using Context): Refs =
val ref = owner.termRef
if reach then
if ref.isTrackableRef then SimpleIdentitySet(ref.reach) else emptySet
if ref.isTrackableRef then SimpleIdentitySet(ref.reach) else emptyRefs
else
if ref.isTracked then SimpleIdentitySet(ref) else emptySet
if ref.isTracked then SimpleIdentitySet(ref) else emptyRefs

/** An extractor for "fresh" capabilities */
object Cap:

def apply(initialHidden: Refs = emptySet)(using Context): CaptureRef =
def apply(initialHidden: Refs = emptyRefs)(using Context): CaptureRef =
if ccConfig.useSepChecks then
AnnotatedType(defn.captureRoot.termRef, Annot(CaptureSet.HiddenSet(initialHidden)))
else
Expand Down
16 changes: 8 additions & 8 deletions compiler/src/dotty/tools/dotc/cc/SepCheck.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import collection.mutable
import core.*
import Symbols.*, Types.*, Flags.*
import Contexts.*, Names.*, Flags.*, Symbols.*, Decorators.*
import CaptureSet.{Refs, emptySet, HiddenSet}
import CaptureSet.{Refs, emptyRefs, HiddenSet}
import config.Printers.capt
import StdNames.nme
import util.{SimpleIdentitySet, EqHashMap, SrcPos}
Expand Down Expand Up @@ -149,7 +149,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
/** The set of capabilities that are hidden by a polymorphic result type
* of some previous definition.
*/
private var defsShadow: Refs = emptySet
private var defsShadow: Refs = emptyRefs

/** A map from definitions to their internal result types.
* Populated during separation checking traversal.
Expand Down Expand Up @@ -243,10 +243,10 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
def hiddenByElem(elem: CaptureRef): Refs = elem match
case Fresh.Cap(hcs) => hcs.elems.filter(!_.isRootCapability) ++ recur(hcs.elems)
case ReadOnlyCapability(ref1) => hiddenByElem(ref1).map(_.readOnly)
case _ => emptySet
case _ => emptyRefs

def recur(refs: Refs): Refs =
(emptySet /: refs): (elems, elem) =>
(emptyRefs /: refs): (elems, elem) =>
if seen.add(elem) then elems ++ hiddenByElem(elem) else elems

recur(refs)
Expand Down Expand Up @@ -335,7 +335,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
def hiddenCaptures = formalCaptures(arg).hidden
def clashFootprint = clashCaptures.footprint
def hiddenFootprint = hiddenCaptures.footprint
def declaredFootprint = deps(arg).map(captures(_)).foldLeft(emptySet)(_ ++ _).footprint
def declaredFootprint = deps(arg).map(captures(_)).foldLeft(emptyRefs)(_ ++ _).footprint
def footprintOverlap = hiddenFootprint.overlapWith(clashFootprint).deduct(declaredFootprint)
report.error(
em"""Separation failure: argument of type ${arg.nuType}
Expand Down Expand Up @@ -500,7 +500,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
case AnnotatedType(parent, _) => explicitRefs(parent)
case AndType(tp1, tp2) => explicitRefs(tp1) ++ explicitRefs(tp2)
case OrType(tp1, tp2) => explicitRefs(tp1) ** explicitRefs(tp2)
case _ => emptySet
case _ => emptyRefs

/** Deduct some elements from `refs` according to the role of the checked type `tpe`:
* - If the the type apears as a (result-) type of a definition of `x`, deduct
Expand Down Expand Up @@ -593,8 +593,8 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
* be explicitly referenced or hidden in some other part.
*/
def checkParts(parts: List[Type]): Unit =
var footprint: Refs = emptySet
var hiddenSet: Refs = emptySet
var footprint: Refs = emptyRefs
var hiddenSet: Refs = emptyRefs
var checked = 0
for part <- parts do

Expand Down

0 comments on commit 071bf19

Please sign in to comment.