Skip to content

Commit abebcf9

Browse files
committed
Change capture elements to union type
1 parent 180a7e9 commit abebcf9

File tree

7 files changed

+54
-11
lines changed

7 files changed

+54
-11
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ object Trees {
3434

3535
val SyntheticUnit: Property.StickyKey[Unit] = Property.StickyKey()
3636

37+
val CaptureVarDef: Property.StickyKey[Unit] = Property.StickyKey()
38+
3739
/** Trees take a parameter indicating what the type of their `tpe` field
3840
* is. Two choices: `Type` or `Untyped`.
3941
* Untyped trees have type `Tree[Untyped]`.

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
386386
/** Property key for contextual Apply trees of the form `fn given arg` */
387387
val KindOfApply: Property.StickyKey[ApplyKind] = Property.StickyKey()
388388

389+
val RetainsAnnot: Property.StickyKey[Unit] = Property.StickyKey()
390+
389391
// ------ Creation methods for untyped only -----------------
390392

391393
def Ident(name: Name)(implicit src: SourceFile): Ident = new Ident(name)
@@ -528,7 +530,16 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
528530
Select(scalaDot(nme.caps), nme.CAPTURE_ROOT)
529531

530532
def makeRetaining(parent: Tree, refs: List[Tree], annotName: TypeName)(using Context): Annotated =
531-
Annotated(parent, New(scalaAnnotationDot(annotName), List(refs)))
533+
var annot: Tree = scalaAnnotationDot(annotName)
534+
if annotName == tpnme.retainsCap then
535+
annot = New(annot, Nil)
536+
else
537+
val trefs =
538+
if refs.isEmpty then ref(defn.NothingType)
539+
else refs.map(SingletonTypeTree).reduce[Tree]((a, b) => makeOrType(a, b))
540+
annot = New(AppliedTypeTree(annot, trefs :: Nil), Nil)
541+
annot.putAttachment(RetainsAnnot, ())
542+
Annotated(parent, annot)
532543

533544
def makeCapsOf(tp: RefTree)(using Context): Tree =
534545
TypeApply(capsInternalDot(nme.capsOf), tp :: Nil)
@@ -563,6 +574,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
563574
def makeAndType(left: Tree, right: Tree)(using Context): AppliedTypeTree =
564575
AppliedTypeTree(ref(defn.andType.typeRef), left :: right :: Nil)
565576

577+
def makeOrType(left: Tree, right: Tree)(using Context): AppliedTypeTree =
578+
AppliedTypeTree(ref(defn.orType.typeRef), left :: right :: Nil)
579+
566580
def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers, isBackquoted: Boolean = false)(using Context): ValDef = {
567581
val vdef = ValDef(pname, tpe, EmptyTree)
568582
if (isBackquoted) vdef.pushAttachment(Backquoted, ())

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,32 @@ extension (tree: Tree)
217217
tree.getAttachment(Captures) match
218218
case Some(refs) => refs
219219
case None =>
220-
val refs = CaptureSet(tree.retainedElems.flatMap(_.toCaptureRefs)*)
221-
//.showing(i"toCaptureSet $tree --> $result", capt)
220+
val refs =
221+
tree match
222+
case Apply(_: TypeApply, _) =>
223+
CaptureSet(tree.retainedElemsFromType*)
224+
case _ =>
225+
CaptureSet(tree.retainedElems.flatMap(_.toCaptureRefs)*)
226+
// println(s"toCaptureSet: $tree -> $refs")
222227
tree.putAttachment(Captures, refs)
223228
refs
224229

230+
def retainedElemsFromType(using Context): List[CaptureRef] =
231+
def collectRefs(tp: Type): List[CaptureRef] = tp match
232+
case tp: CaptureRef if tp.isTrackableRef =>
233+
tp :: Nil
234+
case tp: TypeRef if tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet) =>
235+
tp :: Nil
236+
case OrType(tp1, tp2) =>
237+
collectRefs(tp1) ++ collectRefs(tp2)
238+
case _ =>
239+
Nil
240+
tree match
241+
case Apply(TypeApply(_, refs :: Nil), _) =>
242+
collectRefs(refs.tpe)
243+
case _ =>
244+
Nil
245+
225246
/** The arguments of a @retains, @retainsCap or @retainsByName annotation */
226247
def retainedElems(using Context): List[Tree] = tree match
227248
case Apply(_, Typed(SeqLiteral(elems, _), _) :: Nil) =>

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,9 +1116,7 @@ trait Applications extends Compatibility {
11161116
val fun2 = Applications.retypeSignaturePolymorphicFn(fun1, methType)
11171117
simpleApply(fun2, proto)
11181118
case funRef: TermRef =>
1119-
// println(i"typedApply: $funRef, ${tree.args}, ${funRef.symbol.maybeOwner.isRetains}")
1120-
val applyCtx = if funRef.symbol.maybeOwner.isRetains then ctx.addMode(Mode.InCaptureSet) else ctx
1121-
val app = ApplyTo(tree, fun1, funRef, proto, pt)(using applyCtx)
1119+
val app = ApplyTo(tree, fun1, funRef, proto, pt)
11221120
convertNewGenericArray(
11231121
widenEnumCase(
11241122
postProcessByNameArgs(funRef, app).computeNullable(),

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
718718
else if name.isTermName && ctx.mode.is(Mode.InCaptureSet) then
719719
// If we are in a capture set and the identifier is not a term name,
720720
// try to type it with the same name but as a type
721-
typed(untpd.makeCapsOf(untpd.cpy.Ident(tree)(name.toTypeName)), pt)
721+
// typed(untpd.makeCapsOf(untpd.cpy.Ident(tree)(name.toTypeName)), pt)
722+
typed(untpd.cpy.Ident(tree)(name.toTypeName), pt)
722723
else
723724
errorTree(tree, MissingIdent(tree, kind, name, pt))
724725
end typedIdent
@@ -2538,8 +2539,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25382539
errorTree(tree,
25392540
em"Illegal context bound: ${tycon.tpe} does not take type parameters$selfNote.")
25402541

2541-
def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(using Context): SingletonTypeTree = {
2542+
def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(using Context): Tree = {
25422543
val ref1 = typedExpr(tree.ref, SingletonTypeProto)
2544+
// println(i"typed singleton type $ref1 : ${ref1.tpe}, ${ctx.mode.is(Mode.InCaptureSet)}")
2545+
ref1.tpe match
2546+
case _: TypeRef if ctx.mode.is(Mode.InCaptureSet) => return ref1
2547+
case _ =>
25432548
checkStable(ref1.tpe, tree.srcPos, "singleton type")
25442549
assignType(cpy.SingletonTypeTree(tree)(ref1), ref1)
25452550
}
@@ -3377,7 +3382,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
33773382
end typedPackageDef
33783383

33793384
def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = {
3380-
val annot0 = withMode(Mode.InAnnotation)(typedExpr(tree.annot))
3385+
var annotCtx = ctx.addMode(Mode.InAnnotation)
3386+
if tree.annot.hasAttachment(untpd.RetainsAnnot) then
3387+
annotCtx = annotCtx.addMode(Mode.InCaptureSet)
3388+
val annot0 = typedExpr(tree.annot)(using annotCtx)
33813389
val annot1 = checkAnnotClass(annot0)
33823390
val annotCls = Annotations.annotClass(annot1)
33833391
if annotCls == defn.NowarnAnnot then

library/src/scala/annotation/retains.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ package scala.annotation
1212
* non-standard capturing type syntax.
1313
*/
1414
@experimental
15-
class retains(xs: (Any@retainsArg)*) extends annotation.StaticAnnotation
15+
class retains[Args](xs: (Any @retainsArg)*) extends annotation.StaticAnnotation
1616

1717
/** Equivalent in meaning to `@retains(cap)`, but consumes less bytecode.
1818
*/

library/src/scala/annotation/retainsByName.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package scala.annotation
22

33
/** An annotation that indicates capture of an enclosing by-name type
44
*/
5-
@experimental class retainsByName(xs: (Any@retainsArg)*) extends annotation.StaticAnnotation
5+
@experimental class retainsByName[Args](xs: (Any@retainsArg)*) extends annotation.StaticAnnotation
66

0 commit comments

Comments
 (0)