@@ -76,16 +76,6 @@ object CheckCaptures:
7676 if remaining.accountsFor(firstRef) then
7777 report.warning(em " redundant capture: $remaining already accounts for $firstRef" , ann.srcPos)
7878
79- /** Does this function allow type arguments carrying the universal capability?
80- * Currently this is true only for `erasedValue` since this function is magic in
81- * that is allows to conjure global capabilies from nothing (aside: can we find a
82- * more controlled way to achieve this?).
83- * But it could be generalized to other functions that so that they can take capability
84- * classes as arguments.
85- */
86- private def allowUniversalArguments (fn : Tree )(using Context ): Boolean =
87- fn.symbol == defn.Compiletime_erasedValue
88-
8979class CheckCaptures extends Recheck :
9080 thisPhase =>
9181
@@ -309,6 +299,26 @@ class CheckCaptures extends Recheck:
309299 includeBoxedCaptures(res, tree.srcPos)
310300 res
311301
302+ override def recheckFinish (tpe : Type , tree : Tree , pt : Type )(using Context ): Type =
303+ val typeToCheck = tree match
304+ case _ : Ident | _ : Select | _ : Apply | _ : TypeApply if tree.symbol.unboxesResult =>
305+ tpe
306+ case _ : Try =>
307+ tpe
308+ case ValDef (_, tpt, _) if tree.symbol.is(Mutable ) =>
309+ tree.symbol.info
310+ case _ =>
311+ NoType
312+ if typeToCheck.exists then
313+ typeToCheck.widenDealias match
314+ case wtp @ CapturingType (parent, refs, _) =>
315+ refs.disallowRootCapability { () =>
316+ val kind = if tree.isInstanceOf [ValDef ] then " mutable variable" else " expression"
317+ report.error(em " the $kind's type $wtp is not allowed to capture the root capability `*` " , tree.srcPos)
318+ }
319+ case _ =>
320+ super .recheckFinish(tpe, tree, pt)
321+
312322 override def checkUnit (unit : CompilationUnit )(using Context ): Unit =
313323 Setup (preRecheckPhase, thisPhase, recheckDef)
314324 .traverse(ctx.compilationUnit.tpdTree)
@@ -319,45 +329,6 @@ class CheckCaptures extends Recheck:
319329 show(unit.tpdTree) // this dows not print tree, but makes its variables visible for dependency printing
320330 }
321331
322- def checkNotGlobal (tree : Tree , tp : Type , isVar : Boolean , allArgs : Tree * )(using Context ): Unit =
323- for ref <- tp.captureSet.elems do
324- val isGlobal = ref match
325- case ref : TermRef => ref.isRootCapability
326- case _ => false
327- if isGlobal then
328- val what = if ref.isRootCapability then " universal" else " global"
329- val notAllowed = i " is not allowed to capture the $what capability $ref"
330- def msg =
331- if allArgs.isEmpty then
332- i " ${if isVar then " type of mutable variable" else " result type" } ${tree.knownType}$notAllowed"
333- else tree match
334- case tree : InferredTypeTree =>
335- i """ inferred type argument ${tree.knownType}$notAllowed
336- |
337- |The inferred arguments are: [ ${allArgs.map(_.knownType)}%, %] """
338- case _ => s " type argument $notAllowed"
339- report.error(msg, tree.srcPos)
340-
341- def checkNotGlobal (tree : Tree , allArgs : Tree * )(using Context ): Unit =
342- tree match
343- case LambdaTypeTree (_, restpt) =>
344- checkNotGlobal(restpt, allArgs* )
345- case _ =>
346- checkNotGlobal(tree, tree.knownType, isVar = false , allArgs* )
347-
348- def checkNotGlobalDeep (tree : Tree )(using Context ): Unit =
349- val checker = new TypeTraverser :
350- def traverse (tp : Type ): Unit = tp match
351- case tp : TypeRef =>
352- tp.info match
353- case TypeBounds (_, hi) => traverse(hi)
354- case _ =>
355- case tp : TermRef =>
356- case _ =>
357- checkNotGlobal(tree, tp, isVar = true )
358- traverseChildren(tp)
359- checker.traverse(tree.knownType)
360-
361332 object PostCheck extends TreeTraverser :
362333 def traverse (tree : Tree )(using Context ) = trace{i " post check $tree" } {
363334 tree match
@@ -370,10 +341,6 @@ class CheckCaptures extends Recheck:
370341 checkWellformedPost(annot.tree)
371342 case _ =>
372343 }
373- case tree1 @ TypeApply (fn, args) if ! allowUniversalArguments(fn) =>
374- for arg <- args do
375- // println(i"checking $arg in $tree: ${tree.knownType.captureSet}")
376- checkNotGlobal(arg, args* )
377344 case t : ValOrDefDef if t.tpt.isInstanceOf [InferredTypeTree ] =>
378345 val sym = t.symbol
379346 val isLocal =
@@ -396,10 +363,6 @@ class CheckCaptures extends Recheck:
396363 |The type needs to be declared explicitly. """ , t.srcPos)
397364 case _ =>
398365 inferred.foreachPart(checkPure, StopAt .Static )
399- case t : ValDef if t.symbol.is(Mutable ) =>
400- checkNotGlobalDeep(t.tpt)
401- case t : Try =>
402- checkNotGlobal(t)
403366 case _ =>
404367 traverseChildren(tree)
405368 }
0 commit comments