Skip to content

Commit 04097cd

Browse files
committed
Update extractors
1 parent 0bff38f commit 04097cd

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
@@ -603,6 +603,17 @@ object Capabilities:
603603
def assumedContainsOf(x: TypeRef)(using Context): SimpleIdentitySet[Capability] =
604604
CaptureSet.assumedContains.getOrElse(x, SimpleIdentitySet.empty)
605605

606+
def toType(using Context): Type = this match
607+
case c: RootCapability => defn.captureRoot.termRef
608+
case c: CoreCapability => c
609+
case c: DerivedCapability =>
610+
val c1 = c.underlying.toType
611+
c match
612+
case _: ReadOnly => ReadOnlyCapability(c1)
613+
case _: Reach => ReachCapability(c1)
614+
// TODO: do we need to handle Maybe here?
615+
case _ => c1
616+
606617
def toText(printer: Printer): Text = printer.toTextCapability(this)
607618
end Capability
608619

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
@@ -86,15 +86,24 @@ extension (tree: Tree)
8686
case Apply(TypeApply(_, refs :: Nil), _) => refs.tpe
8787
case _ =>
8888
if tree.symbol.maybeOwner == defn.RetainsCapAnnot
89-
then ref(defn.captureRoot) else NoType
89+
then defn.captureRoot.termRef else NoType
9090

9191
extension (tp: Type)
9292

93-
def retainedElementsRaw(using Context): List[Type] = tp match
93+
def toCapabilities(using Context): List[Capability] = tp match
9494
case ReachCapability(tp1) =>
95-
tp1.reach :: Nil
95+
tp1.toCapabilities.map(_.reach)
9696
case ReadOnlyCapability(tp1) =>
97-
tp1.readOnly :: Nil
97+
tp1.toCapabilities.map(_.readOnly)
98+
case ref: TermRef if ref.isCapRef =>
99+
GlobalCap :: Nil
100+
case ref: Capability if ref.isTrackableRef =>
101+
ref :: Nil
102+
case _ =>
103+
// if this was compiled from cc syntax, problem should have been reported at Typer
104+
throw IllegalCaptureRef(tp)
105+
106+
def retainedElementsRaw(using Context): List[Type] = tp match
98107
case OrType(tp1, tp2) =>
99108
tp1.retainedElementsRaw ++ tp2.retainedElementsRaw
100109
case tp =>
@@ -103,9 +112,7 @@ extension (tp: Type)
103112
else tp :: Nil // should be checked by wellformedness
104113

105114
def retainedElements(using Context): List[Capability] =
106-
retainedElementsRaw.map:
107-
case tp: CaptureRef => tp
108-
case tp => throw IllegalCaptureRef(tp)
115+
retainedElementsRaw.flatMap(_.toCapabilities)
109116

110117
/** Is this type a Capability that can be tracked?
111118
* This is true for
@@ -539,57 +546,25 @@ class CleanupRetains(using Context) extends TypeMap:
539546
RetainingType(tp, defn.NothingType, byName = annot.symbol == defn.RetainsByNameAnnot)
540547
case _ => mapOver(tp)
541548

542-
// /** An extractor for `caps.reachCapability(ref)`, which is used to express a reach
543-
// * capability as a tree in a @retains annotation.
544-
// */
545-
// object ReachCapabilityApply:
546-
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
547-
// case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg)
548-
// case _ => None
549-
550-
// /** An extractor for `caps.readOnlyCapability(ref)`, which is used to express a read-only
551-
// * capability as a tree in a @retains annotation.
552-
// */
553-
// object ReadOnlyCapabilityApply:
554-
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
555-
// case Apply(ro, arg :: Nil) if ro.symbol == defn.Caps_readOnlyCapability => Some(arg)
556-
// case _ => None
557-
558549
abstract class AnnotatedCapability(annotCls: Context ?=> ClassSymbol):
559550
def apply(tp: Type)(using Context): AnnotatedType =
560-
assert(tp.isTrackableRef, i"not a trackable ref: $tp")
561-
tp match
562-
case AnnotatedType(_, annot) =>
563-
assert(!unwrappable.contains(annot.symbol), i"illegal combination of derived capabilities: $annotCls over ${annot.symbol}")
564-
case _ =>
565-
tp match
566-
case tp: Capability => tp.derivedRef(annotCls)
567-
case _ => AnnotatedType(tp, Annotation(annotCls, util.Spans.NoSpan))
551+
AnnotatedType(tp, Annotation(annotCls, util.Spans.NoSpan))
568552

569-
def unapply(tree: AnnotatedType)(using Context): Option[Capability] = tree match
570-
case AnnotatedType(parent: Capability, ann) if ann.hasSymbol(annotCls) => Some(parent)
553+
def unapply(tree: AnnotatedType)(using Context): Option[Type] = tree match
554+
case AnnotatedType(parent: Type, ann) if ann.hasSymbol(annotCls) => Some(parent)
571555
case _ => None
572556

573-
protected def unwrappable(using Context): Set[Symbol]
574557
end AnnotatedCapability
575558

576-
object QualifiedCapability:
577-
def unapply(tree: AnnotatedType)(using Context): Option[Capability] = tree match
578-
case AnnotatedType(parent: Capability, ann)
579-
if defn.capabilityQualifierAnnots.contains(ann.symbol) => Some(parent)
580-
case _ => None
581-
582559
/** An extractor for `ref @readOnlyCapability`, which is used to express
583560
* the read-only capability `ref.rd` as a type.
584561
*/
585-
object ReadOnlyCapability extends AnnotatedCapability(defn.ReadOnlyCapabilityAnnot):
586-
protected def unwrappable(using Context) = Set()
562+
object ReadOnlyCapability extends AnnotatedCapability(defn.ReadOnlyCapabilityAnnot)
587563

588564
/** An extractor for `ref @annotation.internal.reachCapability`, which is used to express
589565
* the reach capability `ref*` as a type.
590566
*/
591-
object ReachCapability extends AnnotatedCapability(defn.ReachCapabilityAnnot):
592-
protected def unwrappable(using Context) = Set(defn.ReadOnlyCapabilityAnnot)
567+
object ReachCapability extends AnnotatedCapability(defn.ReachCapabilityAnnot)
593568

594569
/** An extractor for all kinds of function types as well as method and poly types.
595570
* 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
@@ -1554,11 +1554,6 @@ class Definitions {
15541554
@tu lazy val pureSimpleClasses =
15551555
Set(StringClass, NothingClass, NullClass) ++ ScalaValueClasses()
15561556

1557-
@tu lazy val capabilityQualifierAnnots: Set[Symbol] =
1558-
Set(ReachCapabilityAnnot, ReadOnlyCapabilityAnnot)
1559-
@tu lazy val capabilityWrapperAnnots: Set[Symbol] =
1560-
capabilityQualifierAnnots + RootCapabilityAnnot
1561-
15621557
@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0).asInstanceOf[Array[TypeRef]]
15631558
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
15641559
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)