Skip to content

Commit 11c2d53

Browse files
committed
Improve naming and comments around "disallow roots"
1 parent ea6b0a4 commit 11c2d53

File tree

2 files changed

+32
-31
lines changed

2 files changed

+32
-31
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,11 @@ sealed abstract class CaptureSet extends Showable:
453453
case elem: FreshCap => elem.ccOwner.isContainedIn(rootLimit)
454454
case _ => false
455455

456-
/** Invoke `handler` if this set has (or later aquires) a root capability.
457-
* Excluded are Fresh instances unless their ccOwner is contained in `upto`.
456+
/** Invoke `handler` if this set has (or later aquires) a bad root capability.
457+
* Fresh instances count as good as long as their ccOwner is outside `upto`.
458458
* If `upto` is NoSymbol, all Fresh instances are admitted.
459459
*/
460-
def disallowRootCapability(upto: Symbol)(handler: () => Context ?=> Unit)(using Context): this.type =
460+
def disallowBadRoots(upto: Symbol)(handler: () => Context ?=> Unit)(using Context): this.type =
461461
if elems.exists(isBadRoot(upto, _)) then handler()
462462
this
463463

@@ -817,10 +817,10 @@ object CaptureSet:
817817
|| isConst
818818
|| varState.canRecord && { includeDep(cs); true }
819819

820-
override def disallowRootCapability(upto: Symbol)(handler: () => Context ?=> Unit)(using Context): this.type =
820+
override def disallowBadRoots(upto: Symbol)(handler: () => Context ?=> Unit)(using Context): this.type =
821821
rootLimit = upto
822822
rootAddedHandler = handler
823-
super.disallowRootCapability(upto)(handler)
823+
super.disallowBadRoots(upto)(handler)
824824

825825
override def ensureWellformed(handler: Capability => (Context) ?=> Unit)(using Context): this.type =
826826
newElemAddedHandler = handler
@@ -922,7 +922,7 @@ object CaptureSet:
922922
* Test case: Without that tweak, logger.scala would not compile.
923923
*/
924924
class RefiningVar(owner: Symbol)(using Context) extends Var(owner):
925-
override def disallowRootCapability(upto: Symbol)(handler: () => Context ?=> Unit)(using Context) = this
925+
override def disallowBadRoots(upto: Symbol)(handler: () => Context ?=> Unit)(using Context) = this
926926

927927
/** A variable that is derived from some other variable via a map or filter. */
928928
abstract class DerivedVar(owner: Symbol, initialElems: Refs)(using @constructorOnly ctx: Context)

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

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ object CheckCaptures:
123123
report.error(em"$elem: $tpe is not a legal element of a capture set", ann.srcPos)
124124
ann.retainedSet.retainedElementsRaw.foreach(check)
125125

126-
/** Under the sealed policy, report an error if some part of `tp` contains the
127-
* root capability in its capture set or if it refers to a type parameter that
128-
* could possibly be instantiated with cap in a way that's visible at the type.
126+
/** Disallow bad roots anywhere in type `tp``.
127+
* @param upto controls up to which owner local fresh capabilities should be disallowed.
128+
* See disallowBadRoots for details.
129129
*/
130-
private def disallowRootCapabilitiesIn(tp: Type, upto: Symbol, what: String, have: String, addendum: String, pos: SrcPos)(using Context) =
130+
private def disallowBadRootsIn(tp: Type, upto: Symbol, what: => String, have: => String, addendum: => String, pos: SrcPos)(using Context) =
131131
val check = new TypeTraverser:
132132

133133
private val seen = new EqHashSet[TypeRef]
@@ -154,7 +154,7 @@ object CheckCaptures:
154154
case CapturingType(parent, refs) =>
155155
if variance >= 0 then
156156
val openScopes = openExistentialScopes
157-
refs.disallowRootCapability(upto): () =>
157+
refs.disallowBadRoots(upto): () =>
158158
def part =
159159
if t eq tp then ""
160160
else
@@ -182,7 +182,7 @@ object CheckCaptures:
182182
case t =>
183183
traverseChildren(t)
184184
check.traverse(tp)
185-
end disallowRootCapabilitiesIn
185+
end disallowBadRootsIn
186186

187187
trait CheckerAPI:
188188
/** Complete symbol info of a val or a def */
@@ -493,7 +493,7 @@ class CheckCaptures extends Recheck, SymTransformer:
493493
case c1: CoreCapability =>
494494
CaptureSet.ofType(c1.widen, followResult = false)
495495
capt.println(i"Widen reach $c to $underlying in ${env.owner}")
496-
underlying.disallowRootCapability(NoSymbol): () =>
496+
underlying.disallowBadRoots(NoSymbol): () =>
497497
report.error(em"Local capability $c in ${env.ownerString} cannot have `cap` as underlying capture set", tree.srcPos)
498498
recur(underlying, env, lastEnv)
499499

@@ -537,8 +537,9 @@ class CheckCaptures extends Recheck, SymTransformer:
537537
// Under deferredReaches, don't propagate out of methods inside terms.
538538
// The use set of these methods will be charged when that method is called.
539539

540-
recur(cs, curEnv, null)
541-
useInfos += ((tree, cs, curEnv))
540+
if !cs.isAlwaysEmpty then
541+
recur(cs, curEnv, null)
542+
useInfos += ((tree, cs, curEnv))
542543
end markFree
543544

544545
/** If capability `c` refers to a parameter that is not @use declared, report an error.
@@ -574,16 +575,16 @@ class CheckCaptures extends Recheck, SymTransformer:
574575
case _ =>
575576
tp
576577

577-
/** Under the sealed policy, disallow the root capability in type arguments.
578-
* Type arguments come either from a TypeApply node or from an AppliedType
578+
/** Type arguments come either from a TypeApply node or from an AppliedType
579579
* which represents a trait parent in a template.
580-
* Also, if a corresponding formal type parameter is declared or implied @use,
581-
* charge the deep capture set of the argument to the environent.
580+
* - Disallow global cap and result caps in such arguments.
581+
* - If a corresponding formal type parameter is declared or implied @use,
582+
* charge the deep capture set of the argument to the environent.
582583
* @param fn the type application, of type TypeApply or TypeTree
583584
* @param sym the constructor symbol (could be a method or a val or a class)
584585
* @param args the type arguments
585586
*/
586-
def disallowCapInTypeArgs(fn: Tree, sym: Symbol, args: List[Tree])(using Context): Unit =
587+
def markFreeTypeArgs(fn: Tree, sym: Symbol, args: List[Tree])(using Context): Unit =
587588
def isExempt = sym.isTypeTestOrCast || defn.capsErasedValueMethods.contains(sym)
588589
if !isExempt then
589590
val paramNames = atPhase(thisPhase.prev):
@@ -596,17 +597,17 @@ class CheckCaptures extends Recheck, SymTransformer:
596597

597598
for case (arg: TypeTree, pname) <- args.lazyZip(paramNames) do
598599
def where = if sym.exists then i" in an argument of $sym" else ""
599-
val (addendum, errTree) =
600+
def addendum =
600601
if arg.isInferred
601-
then (i"\nThis is often caused by a local capability$where\nleaking as part of its result.", fn)
602-
else if arg.span.exists then ("", arg)
603-
else ("", fn)
604-
disallowRootCapabilitiesIn(arg.nuType, NoSymbol,
602+
then i"\nThis is often caused by a local capability$where\nleaking as part of its result."
603+
else ""
604+
def errTree = if !arg.isInferred && arg.span.exists then arg else fn
605+
disallowBadRootsIn(arg.nuType, NoSymbol,
605606
i"Type variable $pname of $sym", "be instantiated to", addendum, errTree.srcPos)
606607

607608
val param = fn.symbol.paramNamed(pname)
608609
if param.isUseParam then markFree(arg.nuType.deepCaptureSet, errTree)
609-
end disallowCapInTypeArgs
610+
end markFreeTypeArgs
610611

611612
/** Rechecking idents involves:
612613
* - adding call captures for idents referring to methods
@@ -875,7 +876,7 @@ class CheckCaptures extends Recheck, SymTransformer:
875876
case fun @ Select(qual, nme.apply) => qual.symbol.orElse(fun.symbol)
876877
case fun => fun.symbol
877878
def methDescr = if meth.exists then i"$meth's type " else ""
878-
disallowCapInTypeArgs(tree.fun, meth, tree.args)
879+
markFreeTypeArgs(tree.fun, meth, tree.args)
879880
val funType = super.recheckTypeApply(tree, pt)
880881
val res = resultToFresh(funType, Origin.ResultInstance(funType, meth))
881882
includeCallCaptures(tree.symbol, res, tree)
@@ -997,7 +998,7 @@ class CheckCaptures extends Recheck, SymTransformer:
997998
i"\n\nNote that $sym does not count as local since it is captured by $enclStr"
998999
case _ =>
9991000
""
1000-
disallowRootCapabilitiesIn(
1001+
disallowBadRootsIn(
10011002
tree.tpt.nuType, NoSymbol, i"Mutable $sym", "have type", addendum, sym.srcPos)
10021003
checkInferredResult(super.recheckValDef(tree, sym), tree)
10031004
finally
@@ -1180,7 +1181,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11801181
for case tpt: TypeTree <- impl.parents do
11811182
tpt.tpe match
11821183
case AppliedType(fn, args) =>
1183-
disallowCapInTypeArgs(tpt, fn.typeSymbol, args.map(TypeTree(_)))
1184+
markFreeTypeArgs(tpt, fn.typeSymbol, args.map(TypeTree(_)))
11841185
case _ =>
11851186
ccState.inNestedLevelUnless(cls.is(Module)):
11861187
super.recheckClassDef(tree, impl, cls)
@@ -1213,7 +1214,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12131214
recheck(tree.expr, pt)
12141215
val tp = recheckTryRest(bodyType, tree.cases, tree.finalizer, pt)
12151216
if Feature.enabled(Feature.saferExceptions) then
1216-
disallowRootCapabilitiesIn(tp, ctx.owner,
1217+
disallowBadRootsIn(tp, ctx.owner,
12171218
"The result of `try`", "have type",
12181219
"\nThis is often caused by a locally generated exception capability leaking as part of its result.",
12191220
tree.srcPos)
@@ -1985,7 +1986,7 @@ class CheckCaptures extends Recheck, SymTransformer:
19851986
if !(pos.span.isSynthetic && ctx.reporter.errorsReported)
19861987
&& !arg.typeSymbol.name.is(WildcardParamName)
19871988
then
1988-
CheckCaptures.disallowRootCapabilitiesIn(arg, NoSymbol,
1989+
CheckCaptures.disallowBadRootsIn(arg, NoSymbol,
19891990
"Array", "have element type", "",
19901991
pos)
19911992
traverseChildren(t)

0 commit comments

Comments
 (0)