Skip to content

Commit

Permalink
Revise handing of @uncheckedAnnotation
Browse files Browse the repository at this point in the history
The previous meaning did not do enough in the presence of fresh.
The new meaning is that all universal capture sets under a @uncheckedCaptures
become <fluid> capture sets.
  • Loading branch information
odersky committed Jan 1, 2025
1 parent eae9c07 commit b33b097
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
20 changes: 18 additions & 2 deletions compiler/src/dotty/tools/dotc/cc/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
catch case ex: IllegalCaptureRef =>
report.error(em"Illegal capture reference: ${ex.getMessage.nn}", tptToCheck.srcPos)
parent2
else if ann.symbol == defn.UncheckedCapturesAnnot then
makeUnchecked(apply(parent))
else
t.derivedAnnotatedType(parent1, ann)
case throwsAlias(res, exc) =>
Expand Down Expand Up @@ -439,7 +441,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:

private val paramSigChange = util.EqHashSet[Tree]()

/** Transform type of tree, and remember the transformed type as the type the tree */
/** Transform type of tree, and remember the transformed type as the type the tree
* @pre !(boxed && sym.exists)
*/
private def transformTT(tree: TypeTree, sym: Symbol, boxed: Boolean)(using Context): Unit =
if !tree.hasNuType then
var transformed =
Expand All @@ -450,7 +454,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
if sym.is(Param) && (transformed ne tree.tpe) then
paramSigChange += tree
tree.setNuType(
if boxed then transformed else Fresh.fromCap(transformed, sym))
if boxed then transformed
else if sym.hasAnnotation(defn.UncheckedCapturesAnnot) then makeUnchecked(transformed)
else Fresh.fromCap(transformed, sym))

/** Transform the type of a val or var or the result type of a def */
def transformResultType(tpt: TypeTree, sym: Symbol)(using Context): Unit =
Expand Down Expand Up @@ -818,6 +824,16 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
if variance > 0 then t1
else decorate(t1, Function.const(CaptureSet.Fluid))

/** Replace all universal capture sets in this type by <fluid> */
private def makeUnchecked(using Context): TypeMap = new TypeMap with FollowAliasesMap:
def apply(t: Type) = t match
case t @ CapturingType(parent, refs) =>
val parent1 = this(parent)
if refs.isUniversal then t.derivedCapturingType(parent1, CaptureSet.Fluid)
else t
case Existential(_) => t
case _ => mapFollowingAliases(t)

/** Pull out an embedded capture set from a part of `tp` */
def normalizeCaptures(tp: Type)(using Context): Type = tp match
case tp @ RefinedType(parent @ CapturingType(parent1, refs), rname, rinfo) =>
Expand Down
17 changes: 0 additions & 17 deletions tests/neg-custom-args/captures/explain-under-approx.check

This file was deleted.

7 changes: 7 additions & 0 deletions tests/pos-custom-args/captures/foreach2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import annotation.unchecked.uncheckedCaptures

class ArrayBuffer[T]:
def foreach(op: T => Unit): Unit = ???
def test =
val tasks = new ArrayBuffer[(() => Unit) @uncheckedCaptures]
val _: Unit = tasks.foreach(((task: () => Unit) => task()))

0 comments on commit b33b097

Please sign in to comment.