Skip to content

Commit 9abbb03

Browse files
committed
Represent read-only with a classifier
`x.rd` is now a shorthand for `x.only[caps.Read]`.
1 parent 4689288 commit 9abbb03

File tree

3 files changed

+24
-26
lines changed

3 files changed

+24
-26
lines changed

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

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,33 @@ object Capabilities:
9191
*/
9292
case class Maybe(underlying: Capability) extends DerivedCapability
9393

94-
/** The readonly capability `x.rd`. We have {x.rd} <: {x}.
95-
*
96-
* Read-only capabilities cannot wrap maybe capabilities
97-
* but they can wrap reach capabilities. We have
98-
* (x?).readOnly = (x.rd)?
99-
*/
100-
case class ReadOnly(underlying: ObjectCapability | RootCapability | Reach | Restricted)
101-
extends DerivedCapability
102-
10394
/** The restricted capability `x.only[C]`. We have {x.only[C]} <: {x}.
10495
*
105-
* Restricted capabilities cannot wrap maybe capabilities or read-only capabilities
96+
* Restricted capabilities cannot wrap maybe capabilities
10697
* but they can wrap reach capabilities. We have
10798
* (x?).restrict[T] = (x.restrict[T])?
10899
* (x.rd).restrict[T] = (x.restrict[T]).rd
109100
*/
110-
case class Restricted(underlying: ObjectCapability | RootCapability | Reach, cls: ClassSymbol)
101+
case class Restricted(underlying: CoreCapability | RootCapability | Reach, cls: ClassSymbol)
111102
extends DerivedCapability
112103

104+
/** An extractor for the read-only capability `x.rd`. `x.rd` is represented as
105+
* `c.only[caps.Read]`.
106+
*/
107+
object ReadOnly:
108+
def apply(underlying: CoreCapability | RootCapability | Reach | Restricted)(using Context): Restricted =
109+
Restricted(underlying.stripRestricted.asInstanceOf, defn.Caps_Read)
110+
def unapply(ref: Restricted)(using Context): Option[CoreCapability | RootCapability | Reach] =
111+
if ref.cls == defn.Caps_Read then Some(ref.underlying) else None
112+
113113
/** If `x` is a capability, its reach capability `x*`. `x*` stands for all
114114
* capabilities reachable through `x`.
115115
* We have `{x} <: {x*} <: dcs(x)}` where the deep capture set `dcs(x)` of `x`
116116
* is the union of all capture sets that appear in covariant position in the
117117
* type of `x`. If `x` and `y` are different variables then `{x*}` and `{y*}`
118118
* are unrelated.
119119
*
120-
* Reach capabilities cannot wrap read-only capabilities or maybe capabilities.
120+
* Reach capabilities cannot wrap restricted capabilities or maybe capabilities.
121121
* We have
122122
* (x?).reach = (x.reach)?
123123
* (x.rd).reach = (x.reach).rd
@@ -133,7 +133,7 @@ object Capabilities:
133133
object GlobalCap extends RootCapability:
134134
def descr(using Context) = "the universal root capability"
135135
override val maybe = Maybe(this)
136-
override val readOnly = ReadOnly(this)
136+
override def readOnly(using Context) = ReadOnly(this)
137137
override def restrict(cls: ClassSymbol)(using Context) = Restricted(this, cls)
138138
override def reach = unsupported("cap.reach")
139139
override def singletonCaptureSet(using Context) = CaptureSet.universal
@@ -347,23 +347,21 @@ object Capabilities:
347347
case self: Maybe => self
348348
case _ => cached(Maybe(this))
349349

350-
def readOnly: ReadOnly | Maybe = this match
350+
def readOnly(using Context): Restricted | Maybe = this match
351351
case Maybe(ref1) => Maybe(ref1.readOnly)
352-
case self: ReadOnly => self
353-
case self: (ObjectCapability | RootCapability | Reach | Restricted) => cached(ReadOnly(self))
352+
case self @ ReadOnly(_) => self
353+
case self: (CoreCapability | RootCapability | Reach | Restricted) => cached(ReadOnly(self))
354354

355-
def restrict(cls: ClassSymbol)(using Context): Restricted | ReadOnly | Maybe = this match
355+
def restrict(cls: ClassSymbol)(using Context): Restricted | Maybe = this match
356356
case Maybe(ref1) => Maybe(ref1.restrict(cls))
357-
case ReadOnly(ref1) => ReadOnly(ref1.restrict(cls).asInstanceOf[Restricted])
358357
case self @ Restricted(ref1, prevCls) =>
359358
val combinedCls = leastClassifier(prevCls, cls)
360359
if combinedCls == prevCls then self
361360
else cached(Restricted(ref1, combinedCls))
362-
case self: (ObjectCapability | RootCapability | Reach) => cached(Restricted(self, cls))
361+
case self: (CoreCapability | RootCapability | Reach) => cached(Restricted(self, cls))
363362

364-
def reach: Reach | Restricted | ReadOnly | Maybe = this match
363+
def reach: Reach | Restricted | Maybe = this match
365364
case Maybe(ref1) => Maybe(ref1.reach)
366-
case ReadOnly(ref1) => ReadOnly(ref1.reach.asInstanceOf[Reach | Restricted])
367365
case Restricted(ref1, cls) => Restricted(ref1.reach.asInstanceOf[Reach], cls)
368366
case self: Reach => self
369367
case self: ObjectCapability => cached(Reach(self))
@@ -893,7 +891,7 @@ object Capabilities:
893891
case c: DerivedCapability =>
894892
val c1 = c.underlying.toType
895893
c match
896-
case _: ReadOnly => ReadOnlyCapability(c1)
894+
case ReadOnly(_) => ReadOnlyCapability(c1)
897895
case Restricted(_, cls) => OnlyCapability(c1, cls)
898896
case _: Reach => ReachCapability(c1)
899897
case _: Maybe => MaybeCapability(c1)

tests/neg-custom-args/captures/mutability.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,5 @@
9494
-- Error: tests/neg-custom-args/captures/mutability.scala:45:9 ---------------------------------------------------------
9595
45 | r6().x.set(33) // error
9696
| ^^^^^^^^^^
97-
| Cannot call update method set of Ref[Int]^{cap.rd}
98-
| since its capture set {cap.rd} is read-only.
97+
| Cannot call update method set of Ref[Int]^{r6*.rd}
98+
| since its capture set {r6*.rd} is read-only.

tests/neg-custom-args/captures/mutvars.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,5 @@
9494
-- Error: tests/neg-custom-args/captures/mutvars.scala:44:13 -----------------------------------------------------------
9595
44 | r6().x.fld = 33 // error
9696
| ^^^^^^^^^^^^^^^
97-
| Cannot assign to field fld of Ref[Int]^{cap.rd}
98-
| since its capture set {cap.rd} is read-only.
97+
| Cannot assign to field fld of Ref[Int]^{r6*.rd}
98+
| since its capture set {r6*.rd} is read-only.

0 commit comments

Comments
 (0)