Skip to content

Commit d54f0fc

Browse files
committed
Update classifiers.md
1 parent 2a0ba0e commit d54f0fc

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

docs/_docs/reference/experimental/capture-checking/classifiers.md

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ trait SharedCapability extends Capability Classifier
4646
trait Control extends SharedCapability, Classifier
4747

4848
trait ExclusiveCapability extends Capability
49-
trait Read extends ExclusiveCapability, Classifier
49+
trait Unscoped extends ExclusiveCapability, Classifier
5050
```
5151
Here is a graph showing the hierarchy of predefined capability traits. Classifier traits are underlined.
5252
```
@@ -56,17 +56,18 @@ Here is a graph showing the hierarchy of predefined capability traits. Classifie
5656
/ \
5757
/ \
5858
SharedCapability ExclusiveCapability
59-
----------------
59+
---------------- |
6060
| |
6161
| |
6262
| |
6363
| |
64-
Control Read
65-
------- ----
64+
Control Unscoped
65+
------- --------
6666
```
6767
At the top of the hierarchy, we distinguish between _shared_ and _exclusive_ capabilities in two traits `SharedCapability` and `ExclusiveCapability`. All capability classes we have seen so far are shared.
6868
`ExclusiveCapability` is a base trait for capabilities that
69-
are checked for anti-aliasing restrictions with the rules governed by [separation checking](separation-checking.md). Separation checking is currently an optional extension of capture checking, enabled by a different language import. Since `Capability` is a sealed trait, all capability classes are either shared or exclusive.
69+
are checked for anti-aliasing restrictions with the rules governed by [separation checking](separation-checking.md). Separation checking is currently an optional extension of capture checking, enabled by a different language import. Since `Capability` is a sealed trait, all capability classes are either shared or exclusive. `SharedCapability` is a classifier, but `ExclusiveCapability` is not. Therefore,
70+
exclusive capabilities can have shared capabilities in their capture set but not _vice versa_.
7071

7172
`Control` capabilities are shared. This means they cannot directly or indirectly capture exclusive capabilities such as capabilities that control access to mutable state. Typical `Control` capabilities are:
7273

@@ -76,6 +77,28 @@ are checked for anti-aliasing restrictions with the rules governed by [separatio
7677

7778
These are all expressed by having their capability classes extend `Control`.
7879

80+
### The Unscoped Classifier
81+
82+
Capabilities classified as `Unscoped` can escape their environment. For instance, the following
83+
is permitted:
84+
```scala
85+
class Ref[T](init: T) extends Unscoped
86+
87+
class File:
88+
def read(): String = ...
89+
90+
def withFile[T](op: (f: File^) => T): T =
91+
op(new File)
92+
93+
withFile: f =>
94+
val r: Ref^ = Ref(f.read())
95+
r
96+
```
97+
Here, `r` is a fresh reference that escapes the scope of `withFile`. That's OK only since
98+
`Ref` is classified as `Unscoped`. Since `Unscoped` is a classifier it means that `Ref` cannot
99+
possible capture `f`, which as a `File` is not classified as unscoped. So returning a `Ref`
100+
from a `withFile` does not affect the lifetime of `f`.
101+
79102
### Classifier Restriction
80103

81104
Consider the following problem: The `Try.apply` method takes in its `body` parameter a computation, and runs it while catching any exceptions or `boundary.break` aborts. The exception or break will be re-issued when calling

0 commit comments

Comments
 (0)