@@ -120,11 +120,11 @@ object CheckCaptures:
120120 report.error(em " $elem: $tpe is not a legal element of a capture set " , ann.srcPos)
121121 ann.retainedSet.retainedElementsRaw.foreach(check)
122122
123- /** Under the sealed policy, report an error if some part of `tp` contains the
124- * root capability in its capture set or if it refers to a type parameter that
125- * could possibly be instantiated with cap in a way that's visible at the type .
123+ /** Disallow bad roots anywhere in type `tp``.
124+ * @param upto controls up to which owner local fresh capabilities should be disallowed.
125+ * See disallowBadRoots for details .
126126 */
127- private def disallowRootCapabilitiesIn (tp : Type , upto : Symbol , what : String , have : String , addendum : String , pos : SrcPos )(using Context ) =
127+ private def disallowBadRootsIn (tp : Type , upto : Symbol , what : => String , have : => String , addendum : => String , pos : SrcPos )(using Context ) =
128128 val check = new TypeTraverser :
129129
130130 private val seen = new EqHashSet [TypeRef ]
@@ -151,7 +151,7 @@ object CheckCaptures:
151151 case CapturingType (parent, refs) =>
152152 if variance >= 0 then
153153 val openScopes = openExistentialScopes
154- refs.disallowRootCapability (upto): () =>
154+ refs.disallowBadRoots (upto): () =>
155155 def part =
156156 if t eq tp then " "
157157 else
@@ -179,7 +179,7 @@ object CheckCaptures:
179179 case t =>
180180 traverseChildren(t)
181181 check.traverse(tp)
182- end disallowRootCapabilitiesIn
182+ end disallowBadRootsIn
183183
184184 trait CheckerAPI :
185185 /** Complete symbol info of a val or a def */
@@ -534,8 +534,9 @@ class CheckCaptures extends Recheck, SymTransformer:
534534 // Under deferredReaches, don't propagate out of methods inside terms.
535535 // The use set of these methods will be charged when that method is called.
536536
537- recur(cs, curEnv, null )
538- useInfos += ((tree, cs, curEnv))
537+ if ! cs.isAlwaysEmpty then
538+ recur(cs, curEnv, null )
539+ useInfos += ((tree, cs, curEnv))
539540 end markFree
540541
541542 /** If capability `c` refers to a parameter that is not @use declared, report an error.
@@ -570,16 +571,16 @@ class CheckCaptures extends Recheck, SymTransformer:
570571 case _ =>
571572 tp
572573
573- /** Under the sealed policy, disallow the root capability in type arguments.
574- * Type arguments come either from a TypeApply node or from an AppliedType
574+ /** Type arguments come either from a TypeApply node or from an AppliedType
575575 * which represents a trait parent in a template.
576- * Also, if a corresponding formal type parameter is declared or implied @use,
577- * charge the deep capture set of the argument to the environent.
576+ * - Disallow global cap and result caps in such arguments.
577+ * - If a corresponding formal type parameter is declared or implied @use,
578+ * charge the deep capture set of the argument to the environent.
578579 * @param fn the type application, of type TypeApply or TypeTree
579580 * @param sym the constructor symbol (could be a method or a val or a class)
580581 * @param args the type arguments
581582 */
582- def disallowCapInTypeArgs (fn : Tree , sym : Symbol , args : List [Tree ])(using Context ): Unit =
583+ def markFreeTypeArgs (fn : Tree , sym : Symbol , args : List [Tree ])(using Context ): Unit =
583584 def isExempt = sym.isTypeTestOrCast || defn.capsErasedValueMethods.contains(sym)
584585 if ! isExempt then
585586 val paramNames = atPhase(thisPhase.prev):
@@ -592,17 +593,17 @@ class CheckCaptures extends Recheck, SymTransformer:
592593
593594 for case (arg : TypeTree , pname) <- args.lazyZip(paramNames) do
594595 def where = if sym.exists then i " in an argument of $sym" else " "
595- val ( addendum, errTree) =
596+ def addendum =
596597 if arg.isInferred
597- then ( i " \n This is often caused by a local capability $where\n leaking as part of its result. " , fn)
598- else if arg.span.exists then ( " " , arg)
599- else ( " " , fn)
600- disallowRootCapabilitiesIn (arg.nuType, NoSymbol ,
598+ then i " \n This is often caused by a local capability $where\n leaking as part of its result. "
599+ else " "
600+ def errTree = if ! arg.isInferred && arg.span.exists then arg else fn
601+ disallowBadRootsIn (arg.nuType, NoSymbol ,
601602 i " Type variable $pname of $sym" , " be instantiated to" , addendum, errTree.srcPos)
602603
603604 val param = fn.symbol.paramNamed(pname)
604605 if param.isUseParam then markFree(arg.nuType.deepCaptureSet, errTree)
605- end disallowCapInTypeArgs
606+ end markFreeTypeArgs
606607
607608 /** Rechecking idents involves:
608609 * - adding call captures for idents referring to methods
@@ -870,7 +871,7 @@ class CheckCaptures extends Recheck, SymTransformer:
870871 case fun @ Select (qual, nme.apply) => qual.symbol.orElse(fun.symbol)
871872 case fun => fun.symbol
872873 def methDescr = if meth.exists then i " $meth's type " else " "
873- disallowCapInTypeArgs (tree.fun, meth, tree.args)
874+ markFreeTypeArgs (tree.fun, meth, tree.args)
874875 val funType = super .recheckTypeApply(tree, pt)
875876 val res = resultToFresh(funType, Origin .ResultInstance (funType, meth))
876877 includeCallCaptures(tree.symbol, res, tree)
@@ -986,7 +987,7 @@ class CheckCaptures extends Recheck, SymTransformer:
986987 i " \n\n Note that $sym does not count as local since it is captured by $enclStr"
987988 case _ =>
988989 " "
989- disallowRootCapabilitiesIn (
990+ disallowBadRootsIn (
990991 tree.tpt.nuType, NoSymbol , i " Mutable $sym" , " have type" , addendum, sym.srcPos)
991992 checkInferredResult(super .recheckValDef(tree, sym), tree)
992993 finally
@@ -1169,7 +1170,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11691170 for case tpt : TypeTree <- impl.parents do
11701171 tpt.tpe match
11711172 case AppliedType (fn, args) =>
1172- disallowCapInTypeArgs (tpt, fn.typeSymbol, args.map(TypeTree (_)))
1173+ markFreeTypeArgs (tpt, fn.typeSymbol, args.map(TypeTree (_)))
11731174 case _ =>
11741175 ccState.inNestedLevelUnless(cls.is(Module )):
11751176 super .recheckClassDef(tree, impl, cls)
@@ -1202,7 +1203,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12021203 recheck(tree.expr, pt)
12031204 val tp = recheckTryRest(bodyType, tree.cases, tree.finalizer, pt)
12041205 if Feature .enabled(Feature .saferExceptions) then
1205- disallowRootCapabilitiesIn (tp, ctx.owner,
1206+ disallowBadRootsIn (tp, ctx.owner,
12061207 " The result of `try`" , " have type" ,
12071208 " \n This is often caused by a locally generated exception capability leaking as part of its result." ,
12081209 tree.srcPos)
@@ -1946,7 +1947,7 @@ class CheckCaptures extends Recheck, SymTransformer:
19461947 if ! (pos.span.isSynthetic && ctx.reporter.errorsReported)
19471948 && ! arg.typeSymbol.name.is(WildcardParamName )
19481949 then
1949- CheckCaptures .disallowRootCapabilitiesIn (arg, NoSymbol ,
1950+ CheckCaptures .disallowBadRootsIn (arg, NoSymbol ,
19501951 " Array" , " have element type" , " " ,
19511952 pos)
19521953 traverseChildren(t)
0 commit comments