Skip to content

Commit 565e001

Browse files
committed
Update extractors
1 parent 9d7fd0e commit 565e001

File tree

6 files changed

+34
-53
lines changed

6 files changed

+34
-53
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,17 @@ object Capabilities:
591591
def assumedContainsOf(x: TypeRef)(using Context): SimpleIdentitySet[Capability] =
592592
CaptureSet.assumedContains.getOrElse(x, SimpleIdentitySet.empty)
593593

594+
def toType(using Context): Type = this match
595+
case c: RootCapability => defn.captureRoot.termRef
596+
case c: CoreCapability => c
597+
case c: DerivedCapability =>
598+
val c1 = c.underlying.toType
599+
c match
600+
case _: ReadOnly => ReadOnlyCapability(c1)
601+
case _: Reach => ReachCapability(c1)
602+
// TODO: do we need to handle Maybe here?
603+
case _ => c1
604+
594605
def toText(printer: Printer): Text = printer.toTextCapability(this)
595606
end Capability
596607

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) exte
4242
if symbol == defn.RetainsCapAnnot then
4343
New(symbol.typeRef, Nil)
4444
else
45-
val elems = refs.elems.toList
45+
val elems = refs.elems.toList.map(_.toType)
4646
val trefs =
4747
if elems.isEmpty then defn.NothingType
48-
else elems.reduce[Type]((a, b) => OrType(a, b, soft = false))
48+
else elems.reduce((a, b) => OrType(a, b, soft = false))
4949
New(AppliedType(symbol.typeRef, trefs :: Nil), Nil)
5050

5151
override def symbol(using Context) = cls

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

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,24 @@ extension (tree: Tree)
8989
case Apply(TypeApply(_, refs :: Nil), _) => refs.tpe
9090
case _ =>
9191
if tree.symbol.maybeOwner == defn.RetainsCapAnnot
92-
then ref(defn.captureRoot) else NoType
92+
then defn.captureRoot.termRef else NoType
9393

9494
extension (tp: Type)
9595

96-
def retainedElementsRaw(using Context): List[Type] = tp match
96+
def toCapabilities(using Context): List[Capability] = tp match
9797
case ReachCapability(tp1) =>
98-
tp1.reach :: Nil
98+
tp1.toCapabilities.map(_.reach)
9999
case ReadOnlyCapability(tp1) =>
100-
tp1.readOnly :: Nil
100+
tp1.toCapabilities.map(_.readOnly)
101+
case ref: TermRef if ref.isCapRef =>
102+
GlobalCap :: Nil
103+
case ref: Capability if ref.isTrackableRef =>
104+
ref :: Nil
105+
case _ =>
106+
// if this was compiled from cc syntax, problem should have been reported at Typer
107+
throw IllegalCaptureRef(tp)
108+
109+
def retainedElementsRaw(using Context): List[Type] = tp match
101110
case OrType(tp1, tp2) =>
102111
tp1.retainedElementsRaw ++ tp2.retainedElementsRaw
103112
case tp =>
@@ -106,9 +115,7 @@ extension (tp: Type)
106115
else tp :: Nil // should be checked by wellformedness
107116

108117
def retainedElements(using Context): List[Capability] =
109-
retainedElementsRaw.map:
110-
case tp: CaptureRef => tp
111-
case tp => throw IllegalCaptureRef(tp)
118+
retainedElementsRaw.flatMap(_.toCapabilities)
112119

113120
/** Is this type a Capability that can be tracked?
114121
* This is true for
@@ -562,57 +569,25 @@ trait FollowAliasesMap(using Context) extends TypeMap:
562569
else t
563570
else mapOver(t)
564571

565-
// /** An extractor for `caps.reachCapability(ref)`, which is used to express a reach
566-
// * capability as a tree in a @retains annotation.
567-
// */
568-
// object ReachCapabilityApply:
569-
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
570-
// case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg)
571-
// case _ => None
572-
573-
// /** An extractor for `caps.readOnlyCapability(ref)`, which is used to express a read-only
574-
// * capability as a tree in a @retains annotation.
575-
// */
576-
// object ReadOnlyCapabilityApply:
577-
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
578-
// case Apply(ro, arg :: Nil) if ro.symbol == defn.Caps_readOnlyCapability => Some(arg)
579-
// case _ => None
580-
581572
abstract class AnnotatedCapability(annotCls: Context ?=> ClassSymbol):
582573
def apply(tp: Type)(using Context): AnnotatedType =
583-
assert(tp.isTrackableRef, i"not a trackable ref: $tp")
584-
tp match
585-
case AnnotatedType(_, annot) =>
586-
assert(!unwrappable.contains(annot.symbol), i"illegal combination of derived capabilities: $annotCls over ${annot.symbol}")
587-
case _ =>
588-
tp match
589-
case tp: Capability => tp.derivedRef(annotCls)
590-
case _ => AnnotatedType(tp, Annotation(annotCls, util.Spans.NoSpan))
574+
AnnotatedType(tp, Annotation(annotCls, util.Spans.NoSpan))
591575

592-
def unapply(tree: AnnotatedType)(using Context): Option[Capability] = tree match
593-
case AnnotatedType(parent: Capability, ann) if ann.hasSymbol(annotCls) => Some(parent)
576+
def unapply(tree: AnnotatedType)(using Context): Option[Type] = tree match
577+
case AnnotatedType(parent: Type, ann) if ann.hasSymbol(annotCls) => Some(parent)
594578
case _ => None
595579

596-
protected def unwrappable(using Context): Set[Symbol]
597580
end AnnotatedCapability
598581

599-
object QualifiedCapability:
600-
def unapply(tree: AnnotatedType)(using Context): Option[Capability] = tree match
601-
case AnnotatedType(parent: Capability, ann)
602-
if defn.capabilityQualifierAnnots.contains(ann.symbol) => Some(parent)
603-
case _ => None
604-
605582
/** An extractor for `ref @readOnlyCapability`, which is used to express
606583
* the read-only capability `ref.rd` as a type.
607584
*/
608-
object ReadOnlyCapability extends AnnotatedCapability(defn.ReadOnlyCapabilityAnnot):
609-
protected def unwrappable(using Context) = Set()
585+
object ReadOnlyCapability extends AnnotatedCapability(defn.ReadOnlyCapabilityAnnot)
610586

611587
/** An extractor for `ref @annotation.internal.reachCapability`, which is used to express
612588
* the reach capability `ref*` as a type.
613589
*/
614-
object ReachCapability extends AnnotatedCapability(defn.ReachCapabilityAnnot):
615-
protected def unwrappable(using Context) = Set(defn.ReadOnlyCapabilityAnnot)
590+
object ReachCapability extends AnnotatedCapability(defn.ReachCapabilityAnnot)
616591

617592
/** An extractor for all kinds of function types as well as method and poly types.
618593
* It includes aliases of function types such as `=>`. TODO: Can we do without?

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,11 +1549,6 @@ class Definitions {
15491549
@tu lazy val pureSimpleClasses =
15501550
Set(StringClass, NothingClass, NullClass) ++ ScalaValueClasses()
15511551

1552-
@tu lazy val capabilityQualifierAnnots: Set[Symbol] =
1553-
Set(ReachCapabilityAnnot, ReadOnlyCapabilityAnnot)
1554-
@tu lazy val capabilityWrapperAnnots: Set[Symbol] =
1555-
capabilityQualifierAnnots + RootCapabilityAnnot
1556-
15571552
@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0).asInstanceOf[Array[TypeRef]]
15581553
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
15591554
def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n)

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
313313
def arrowText: Text = restp match
314314
case AnnotatedType(parent, ann) if ann.symbol == defn.RetainsByNameAnnot =>
315315
ann.tree.retainedSet.retainedElementsRaw match
316-
case (ref: CaptureRef) :: Nil if ref.isCap => Str("=>")
316+
case (ref: TermRef) :: Nil if ref.symbol == defn.captureRoot => Str("=>")
317317
case refs => Str("->") ~ toTextRetainedElems(refs.map(r => ast.tpd.TypeTree(r)))
318318
case _ =>
319319
if Feature.pureFunsEnabled then "->" else "=>"

tests/pos-custom-args/captures/i23170.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ trait A
55
extension (a: A^{cap.rd})
66
def await = ()
77

8-
def awaitA[C <: {cap.rd}](a: A^{C}) = a.await
8+
def awaitA[C^ <: {cap.rd}](a: A^{C}) = a.await

0 commit comments

Comments
 (0)