Skip to content

Commit b33b097

Browse files
committed
Revise handing of @uncheckedAnnotation
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.
1 parent eae9c07 commit b33b097

File tree

3 files changed

+25
-19
lines changed

3 files changed

+25
-19
lines changed

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
356356
catch case ex: IllegalCaptureRef =>
357357
report.error(em"Illegal capture reference: ${ex.getMessage.nn}", tptToCheck.srcPos)
358358
parent2
359+
else if ann.symbol == defn.UncheckedCapturesAnnot then
360+
makeUnchecked(apply(parent))
359361
else
360362
t.derivedAnnotatedType(parent1, ann)
361363
case throwsAlias(res, exc) =>
@@ -439,7 +441,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
439441

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

442-
/** Transform type of tree, and remember the transformed type as the type the tree */
444+
/** Transform type of tree, and remember the transformed type as the type the tree
445+
* @pre !(boxed && sym.exists)
446+
*/
443447
private def transformTT(tree: TypeTree, sym: Symbol, boxed: Boolean)(using Context): Unit =
444448
if !tree.hasNuType then
445449
var transformed =
@@ -450,7 +454,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
450454
if sym.is(Param) && (transformed ne tree.tpe) then
451455
paramSigChange += tree
452456
tree.setNuType(
453-
if boxed then transformed else Fresh.fromCap(transformed, sym))
457+
if boxed then transformed
458+
else if sym.hasAnnotation(defn.UncheckedCapturesAnnot) then makeUnchecked(transformed)
459+
else Fresh.fromCap(transformed, sym))
454460

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

827+
/** Replace all universal capture sets in this type by <fluid> */
828+
private def makeUnchecked(using Context): TypeMap = new TypeMap with FollowAliasesMap:
829+
def apply(t: Type) = t match
830+
case t @ CapturingType(parent, refs) =>
831+
val parent1 = this(parent)
832+
if refs.isUniversal then t.derivedCapturingType(parent1, CaptureSet.Fluid)
833+
else t
834+
case Existential(_) => t
835+
case _ => mapFollowingAliases(t)
836+
821837
/** Pull out an embedded capture set from a part of `tp` */
822838
def normalizeCaptures(tp: Type)(using Context): Type = tp match
823839
case tp @ RefinedType(parent @ CapturingType(parent1, refs), rname, rinfo) =>

tests/neg-custom-args/captures/explain-under-approx.check

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import annotation.unchecked.uncheckedCaptures
2+
3+
class ArrayBuffer[T]:
4+
def foreach(op: T => Unit): Unit = ???
5+
def test =
6+
val tasks = new ArrayBuffer[(() => Unit) @uncheckedCaptures]
7+
val _: Unit = tasks.foreach(((task: () => Unit) => task()))

0 commit comments

Comments
 (0)