You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/_docs/reference/experimental/capture-checking/mutability.md
+20-9Lines changed: 20 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -239,6 +239,20 @@ class Arr[T](n: Int) extends Mutable:
239
239
An example of a `Stateful` and `Unscoped` capability that is _not_`Separate` would be a
240
240
facade class that reveals some part of an underlying `Mutable` capability.
241
241
242
+
## Arrays
243
+
244
+
The class `scala.Array` is considered a `Mutable` class if [separation checking](./separation-checking.md) is enabled. In that context, class Array can be considered to be declared roughly as follows:
245
+
```scala
246
+
classArray[T] extendsMutable:
247
+
deflength:Int
248
+
defapply(i: Int):T
249
+
update defupdate(i: Int, x: T):Unit
250
+
```
251
+
In fact, for technical reasons `Array` cannot extend `Mutable` or any other new traits beyond what is supported by the JVM. But for the purposes of capture and separation checking, it is still a considered a `Mutable` class.
252
+
253
+
By contrast, none of the mutable collections in the Scala standard library extend currently `Stateful` or `Mutable`. So to experiment with mutable collections, an
254
+
alternative class library has to be used.
255
+
242
256
## Read-only Capabilities
243
257
244
258
If `x` is an exclusive capability of a type extending `Stateful`, `x.rd` is its associated _read-only_ capability.
@@ -388,7 +402,9 @@ ro.set(22) // disallowed, since `ro` is read-only access
388
402
389
403
## Untracked Vars
390
404
391
-
Sometimes, disallowing assignments to mutable fields from normal methods is too restrictive. For instance:
405
+
Under [separation checking](./separation-checking.md), mutable fields are allowed to be declared only in `Stateful` classes. Updates to these fields can then only happen in update methods of these classes.
406
+
407
+
But sometimes, disallowing assignments to mutable fields from normal methods is too restrictive. For instance:
392
408
```scala
393
409
importcaps.unsafe.untrackedCaptures
394
410
@@ -401,17 +417,12 @@ class Cache[T](eval: () -> T):
401
417
known =true
402
418
x
403
419
```
404
-
Note that, even though `Cache`has mutable variables, it is not declared as a `Stateful` class. In this case, the mutable field `x` is used to store the result of a pure function `eval` and field `known` reflects whether `eval` was called. This is equivalent to just calling `eval()` directly but can be more efficient since the cached value is evaluated at most once. So from a semantic standpoint, it should not be necessary to make `force` an update method, even though it does assign to `x`.
420
+
Note that`Cache` is not declared as a `Stateful` class, even though it has mutable fields. In this case, the mutable field `x` is used to store the result of a pure function `eval` and field `known` reflects whether `eval` was called. This is equivalent to just calling `eval()` directly but can be more efficient since the cached value is evaluated at most once. So from a semantic standpoint, it should not be necessary to make `Cache` a `Stateful` class with `force`as an update method, even though `force` does assign to `x`.
405
421
406
-
We can avoid the need for update methods by annotating mutable fields with `@untrackedCaptures`. Assignments to untracked mutable field are then not checked for read-only restrictions. The `@untrackedCaptures` annotation can be imported from the `scala.caps.unsafe` object. It is up to the developer
422
+
We can avoid the need for stateful classes and update methods by annotating mutable fields with `@untrackedCaptures`. Assignments to untracked mutable fields are then not checked for read-only restrictions. The `@untrackedCaptures` annotation can be imported from the `scala.caps.unsafe` object. It is up to the developer
407
423
to use `@untrackedCaptures` responsibly so that it does not hide visible side effects on mutable state.
408
424
409
-
Note that at the moment an assignment to a variable is restricted _only_ if the variable is a field of a `Stateful` class. Fields of other classes and local variables are currently not checked. So the `Cache` class above would in fact
410
-
currently compile without the addition of `@untrackedCaptures`.
411
-
412
-
But is planned to tighten the rules in the future so that mutable fields that are not annotated with `@untrackedCaptures` can be declared only in classes extending `Stateful`. This means that all assignments to mutable fields would be checked with the read-only restriction, and `@untrackedCapture`s would become essential as an escape hatch.
413
-
414
-
By contrast, it is not planned to check assignments to local mutable variables, which are not fields of some class. So `@untrackedCaptures` is disallowed for such local variables.
425
+
Note that the are no restrictions on assignments to local mutable variables, which are not fields of some class. So `@untrackedCaptures` is disallowed for such local variables.
415
426
416
427
The `untrackedCaptures` annotation can also be used in some other contexts unrelated to mutable variables. These are described in its [doc comment](https://www.scala-lang.org/api/current/scala/caps/unsafe$$untrackedCaptures.html).
0 commit comments