@@ -123,11 +123,11 @@ object CheckCaptures:
123
123
report.error(em " $elem: $tpe is not a legal element of a capture set " , ann.srcPos)
124
124
ann.retainedSet.retainedElementsRaw.foreach(check)
125
125
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 .
129
129
*/
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 ) =
131
131
val check = new TypeTraverser :
132
132
133
133
private val seen = new EqHashSet [TypeRef ]
@@ -154,7 +154,7 @@ object CheckCaptures:
154
154
case CapturingType (parent, refs) =>
155
155
if variance >= 0 then
156
156
val openScopes = openExistentialScopes
157
- refs.disallowRootCapability (upto): () =>
157
+ refs.disallowBadRoots (upto): () =>
158
158
def part =
159
159
if t eq tp then " "
160
160
else
@@ -182,7 +182,7 @@ object CheckCaptures:
182
182
case t =>
183
183
traverseChildren(t)
184
184
check.traverse(tp)
185
- end disallowRootCapabilitiesIn
185
+ end disallowBadRootsIn
186
186
187
187
trait CheckerAPI :
188
188
/** Complete symbol info of a val or a def */
@@ -493,7 +493,7 @@ class CheckCaptures extends Recheck, SymTransformer:
493
493
case c1 : CoreCapability =>
494
494
CaptureSet .ofType(c1.widen, followResult = false )
495
495
capt.println(i " Widen reach $c to $underlying in ${env.owner}" )
496
- underlying.disallowRootCapability (NoSymbol ): () =>
496
+ underlying.disallowBadRoots (NoSymbol ): () =>
497
497
report.error(em " Local capability $c in ${env.ownerString} cannot have `cap` as underlying capture set " , tree.srcPos)
498
498
recur(underlying, env, lastEnv)
499
499
@@ -537,8 +537,9 @@ class CheckCaptures extends Recheck, SymTransformer:
537
537
// Under deferredReaches, don't propagate out of methods inside terms.
538
538
// The use set of these methods will be charged when that method is called.
539
539
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))
542
543
end markFree
543
544
544
545
/** If capability `c` refers to a parameter that is not @use declared, report an error.
@@ -574,16 +575,16 @@ class CheckCaptures extends Recheck, SymTransformer:
574
575
case _ =>
575
576
tp
576
577
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
579
579
* 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.
582
583
* @param fn the type application, of type TypeApply or TypeTree
583
584
* @param sym the constructor symbol (could be a method or a val or a class)
584
585
* @param args the type arguments
585
586
*/
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 =
587
588
def isExempt = sym.isTypeTestOrCast || defn.capsErasedValueMethods.contains(sym)
588
589
if ! isExempt then
589
590
val paramNames = atPhase(thisPhase.prev):
@@ -596,17 +597,17 @@ class CheckCaptures extends Recheck, SymTransformer:
596
597
597
598
for case (arg : TypeTree , pname) <- args.lazyZip(paramNames) do
598
599
def where = if sym.exists then i " in an argument of $sym" else " "
599
- val ( addendum, errTree) =
600
+ def addendum =
600
601
if arg.isInferred
601
- then ( i " \n This is often caused by a local capability $where\n leaking 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 " \n This is often caused by a local capability $where\n leaking 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 ,
605
606
i " Type variable $pname of $sym" , " be instantiated to" , addendum, errTree.srcPos)
606
607
607
608
val param = fn.symbol.paramNamed(pname)
608
609
if param.isUseParam then markFree(arg.nuType.deepCaptureSet, errTree)
609
- end disallowCapInTypeArgs
610
+ end markFreeTypeArgs
610
611
611
612
/** Rechecking idents involves:
612
613
* - adding call captures for idents referring to methods
@@ -875,7 +876,7 @@ class CheckCaptures extends Recheck, SymTransformer:
875
876
case fun @ Select (qual, nme.apply) => qual.symbol.orElse(fun.symbol)
876
877
case fun => fun.symbol
877
878
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)
879
880
val funType = super .recheckTypeApply(tree, pt)
880
881
val res = resultToFresh(funType, Origin .ResultInstance (funType, meth))
881
882
includeCallCaptures(tree.symbol, res, tree)
@@ -997,7 +998,7 @@ class CheckCaptures extends Recheck, SymTransformer:
997
998
i " \n\n Note that $sym does not count as local since it is captured by $enclStr"
998
999
case _ =>
999
1000
" "
1000
- disallowRootCapabilitiesIn (
1001
+ disallowBadRootsIn (
1001
1002
tree.tpt.nuType, NoSymbol , i " Mutable $sym" , " have type" , addendum, sym.srcPos)
1002
1003
checkInferredResult(super .recheckValDef(tree, sym), tree)
1003
1004
finally
@@ -1180,7 +1181,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1180
1181
for case tpt : TypeTree <- impl.parents do
1181
1182
tpt.tpe match
1182
1183
case AppliedType (fn, args) =>
1183
- disallowCapInTypeArgs (tpt, fn.typeSymbol, args.map(TypeTree (_)))
1184
+ markFreeTypeArgs (tpt, fn.typeSymbol, args.map(TypeTree (_)))
1184
1185
case _ =>
1185
1186
ccState.inNestedLevelUnless(cls.is(Module )):
1186
1187
super .recheckClassDef(tree, impl, cls)
@@ -1213,7 +1214,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1213
1214
recheck(tree.expr, pt)
1214
1215
val tp = recheckTryRest(bodyType, tree.cases, tree.finalizer, pt)
1215
1216
if Feature .enabled(Feature .saferExceptions) then
1216
- disallowRootCapabilitiesIn (tp, ctx.owner,
1217
+ disallowBadRootsIn (tp, ctx.owner,
1217
1218
" The result of `try`" , " have type" ,
1218
1219
" \n This is often caused by a locally generated exception capability leaking as part of its result." ,
1219
1220
tree.srcPos)
@@ -1985,7 +1986,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1985
1986
if ! (pos.span.isSynthetic && ctx.reporter.errorsReported)
1986
1987
&& ! arg.typeSymbol.name.is(WildcardParamName )
1987
1988
then
1988
- CheckCaptures .disallowRootCapabilitiesIn (arg, NoSymbol ,
1989
+ CheckCaptures .disallowBadRootsIn (arg, NoSymbol ,
1989
1990
" Array" , " have element type" , " " ,
1990
1991
pos)
1991
1992
traverseChildren(t)
0 commit comments