@@ -144,7 +144,7 @@ object CheckCaptures:
144
144
* or if it refers to an unsealed type parameter that could possibly be instantiated with
145
145
* cap in a way that's visible at the type.
146
146
*/
147
- def disallowRootCapabilitiesIn (tp : Type , carrier : Symbol , what : String , have : String , addendum : String , pos : SrcPos )(using Context ) =
147
+ private def disallowRootCapabilitiesIn (tp : Type , carrier : Symbol , what : String , have : String , addendum : String , pos : SrcPos )(using Context ) =
148
148
val check = new TypeTraverser :
149
149
extension (tparam : Symbol ) def isParametricIn (carrier : Symbol ): Boolean =
150
150
val encl = carrier.owner.enclosingMethodOrClass
@@ -172,9 +172,9 @@ object CheckCaptures:
172
172
traverse(hi)
173
173
case _ =>
174
174
traverseChildren(t)
175
- case AnnotatedType (tp , ann) if ann.symbol == defn.UncheckedCapturesAnnot =>
175
+ case AnnotatedType (_ , ann) if ann.symbol == defn.UncheckedCapturesAnnot =>
176
176
()
177
- case _ =>
177
+ case t =>
178
178
if variance >= 0 then
179
179
t.captureSet.disallowRootCapability: () =>
180
180
def part = if t eq tp then " " else i " the part $t of "
@@ -534,6 +534,20 @@ class CheckCaptures extends Recheck, SymTransformer:
534
534
else ownType
535
535
end instantiate
536
536
537
+ override def recheckTypeApply (tree : TypeApply , pt : Type )(using Context ): Type =
538
+ if allowUniversalInBoxed then
539
+ val TypeApply (fn, args) = tree
540
+ val polyType = atPhase(thisPhase.prev):
541
+ fn.tpe.widen.asInstanceOf [TypeLambda ]
542
+ for case (arg : TypeTree , pinfo, pname) <- args.lazyZip(polyType.paramInfos).lazyZip((polyType.paramNames)) do
543
+ if pinfo.bounds.hi.hasAnnotation(defn.Caps_SealedAnnot ) then
544
+ def where = if fn.symbol.exists then i " in an argument of ${fn.symbol}" else " "
545
+ disallowRootCapabilitiesIn(arg.knownType, fn.symbol,
546
+ i " Sealed type variable $pname" , " be instantiated to" ,
547
+ i " This is often caused by a local capability $where\n leaking as part of its result. " ,
548
+ tree.srcPos)
549
+ super .recheckTypeApply(tree, pt)
550
+
537
551
override def recheckClosure (tree : Closure , pt : Type , forceDependent : Boolean )(using Context ): Type =
538
552
val cs = capturedVars(tree.meth.symbol)
539
553
capt.println(i " typing closure $tree with cvs $cs" )
@@ -574,7 +588,11 @@ class CheckCaptures extends Recheck, SymTransformer:
574
588
override def recheckValDef (tree : ValDef , sym : Symbol )(using Context ): Type =
575
589
try
576
590
if sym.is(Module ) then sym.info // Modules are checked by checking the module class
577
- else checkInferredResult(super .recheckValDef(tree, sym), tree)
591
+ else
592
+ if sym.is(Mutable ) && ! sym.hasAnnotation(defn.UncheckedCapturesAnnot ) then
593
+ disallowRootCapabilitiesIn(tree.tpt.knownType, sym,
594
+ i " mutable $sym" , " have type" , " " , sym.srcPos)
595
+ checkInferredResult(super .recheckValDef(tree, sym), tree)
578
596
finally
579
597
if ! sym.is(Param ) then
580
598
// Parameters with inferred types belong to anonymous methods. We need to wait
0 commit comments