Skip to content

Commit 995a2dc

Browse files
committed
Change capture elements to union type
1 parent fd75c76 commit 995a2dc

File tree

6 files changed

+52
-11
lines changed

6 files changed

+52
-11
lines changed

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)
@@ -555,6 +566,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
555566
def makeAndType(left: Tree, right: Tree)(using Context): AppliedTypeTree =
556567
AppliedTypeTree(ref(defn.andType.typeRef), left :: right :: Nil)
557568

569+
def makeOrType(left: Tree, right: Tree)(using Context): AppliedTypeTree =
570+
AppliedTypeTree(ref(defn.orType.typeRef), left :: right :: Nil)
571+
558572
def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers, isBackquoted: Boolean = false)(using Context): ValDef = {
559573
val vdef = ValDef(pname, tpe, EmptyTree)
560574
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
@@ -75,11 +75,32 @@ extension (tree: Tree)
7575
tree.getAttachment(Captures) match
7676
case Some(refs) => refs
7777
case None =>
78-
val refs = CaptureSet(tree.retainedElems.flatMap(_.toCaptureRefs)*)
79-
//.showing(i"toCaptureSet $tree --> $result", capt)
78+
val refs =
79+
tree match
80+
case Apply(_: TypeApply, _) =>
81+
CaptureSet(tree.retainedElemsFromType*)
82+
case _ =>
83+
CaptureSet(tree.retainedElems.flatMap(_.toCaptureRefs)*)
84+
// println(s"toCaptureSet: $tree -> $refs")
8085
tree.putAttachment(Captures, refs)
8186
refs
8287

88+
def retainedElemsFromType(using Context): List[CaptureRef] =
89+
def collectRefs(tp: Type): List[CaptureRef] = tp match
90+
case tp: CaptureRef if tp.isTrackableRef =>
91+
tp :: Nil
92+
case tp: TypeRef if tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet) =>
93+
tp :: Nil
94+
case OrType(tp1, tp2) =>
95+
collectRefs(tp1) ++ collectRefs(tp2)
96+
case _ =>
97+
Nil
98+
tree match
99+
case Apply(TypeApply(_, refs :: Nil), _) =>
100+
collectRefs(refs.tpe)
101+
case _ =>
102+
Nil
103+
83104
/** The arguments of a @retains, @retainsCap or @retainsByName annotation */
84105
def retainedElems(using Context): List[Tree] = tree match
85106
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
@@ -1117,9 +1117,7 @@ trait Applications extends Compatibility {
11171117
val fun2 = Applications.retypeSignaturePolymorphicFn(fun1, methType)
11181118
simpleApply(fun2, proto)
11191119
case funRef: TermRef =>
1120-
// println(i"typedApply: $funRef, ${tree.args}, ${funRef.symbol.maybeOwner.isRetains}")
1121-
val applyCtx = if funRef.symbol.maybeOwner.isRetains then ctx.addMode(Mode.InCaptureSet) else ctx
1122-
val app = ApplyTo(tree, fun1, funRef, proto, pt)(using applyCtx)
1120+
val app = ApplyTo(tree, fun1, funRef, proto, pt)
11231121
convertNewGenericArray(
11241122
widenEnumCase(
11251123
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
@@ -2540,8 +2541,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25402541
errorTree(tree,
25412542
em"Illegal context bound: ${tycon.tpe} does not take type parameters$selfNote.")
25422543

2543-
def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(using Context): SingletonTypeTree = {
2544+
def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(using Context): Tree = {
25442545
val ref1 = typedExpr(tree.ref, SingletonTypeProto)
2546+
// println(i"typed singleton type $ref1 : ${ref1.tpe}, ${ctx.mode.is(Mode.InCaptureSet)}")
2547+
ref1.tpe match
2548+
case _: TypeRef if ctx.mode.is(Mode.InCaptureSet) => return ref1
2549+
case _ =>
25452550
checkStable(ref1.tpe, tree.srcPos, "singleton type")
25462551
assignType(cpy.SingletonTypeTree(tree)(ref1), ref1)
25472552
}
@@ -3404,7 +3409,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
34043409
end typedPackageDef
34053410

34063411
def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = {
3407-
val annot0 = withMode(Mode.InAnnotation)(typedExpr(tree.annot))
3412+
var annotCtx = ctx.addMode(Mode.InAnnotation)
3413+
if tree.annot.hasAttachment(untpd.RetainsAnnot) then
3414+
annotCtx = annotCtx.addMode(Mode.InCaptureSet)
3415+
val annot0 = typedExpr(tree.annot)(using annotCtx)
34083416
val annot1 = checkAnnotClass(annot0)
34093417
val annotCls = Annotations.annotClass(annot1)
34103418
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)