Skip to content

Commit 676b85f

Browse files
committed
Changes to Mutable
1. Mutable and ExclsuiveCapability are not longer classifiers. This means Mutable classes can capture other capabilities. Red is still a classifier. 2. Update methods in nested classes can access exclsuive capabilities external to enclosing classes.
1 parent b1a5500 commit 676b85f

39 files changed

+484
-156
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,12 +573,12 @@ class CheckCaptures extends Recheck, SymTransformer:
573573
// fresh capabilities. We do check that they hide no parameter reach caps in checkEscapingUses
574574
case _ =>
575575

576-
def checkReadOnlyMethod(included: CaptureSet, env: Env): Unit =
576+
def checkReadOnlyMethod(included: CaptureSet, meth: Symbol): Unit =
577577
included.checkAddedElems: elem =>
578578
if elem.isExclusive then
579579
report.error(
580-
em"""Read-only ${env.owner} accesses exclusive capability $elem;
581-
|${env.owner} should be declared an update method to allow this.""",
580+
em"""Read-only $meth accesses exclusive capability $elem;
581+
|$meth should be declared an update method to allow this.""",
582582
tree.srcPos)
583583

584584
def recur(cs: CaptureSet, env: Env, lastEnv: Env | Null): Unit =
@@ -599,7 +599,7 @@ class CheckCaptures extends Recheck, SymTransformer:
599599
val nextEnv = nextEnvToCharge(env)
600600
if nextEnv != null && !nextEnv.owner.isStaticOwner then
601601
if env.owner.isReadOnlyMethodOrLazyVal && nextEnv.owner != env.owner then
602-
checkReadOnlyMethod(included, env)
602+
checkReadOnlyMethod(included, env.owner)
603603
recur(included, nextEnv, env)
604604
// Under deferredReaches, don't propagate out of methods inside terms.
605605
// The use set of these methods will be charged when that method is called.

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ object Mutability:
4747

4848
extension (sym: Symbol)
4949
/** An update method is either a method marked with `update` or
50-
* a setter of a non-transparent var.
50+
* a setter of a non-transparent var. `update` is implicit for `consume` methods
51+
* of Mutable classes.
5152
*/
5253
def isUpdateMethod(using Context): Boolean =
5354
sym.isAllOf(Mutable | Method)
@@ -63,8 +64,9 @@ object Mutability:
6364
private def inExclusivePartOf(cls: Symbol)(using Context): Exclusivity =
6465
import Exclusivity.*
6566
if sym == cls then OK // we are directly in `cls` or in one of its constructors
67+
else if sym.isUpdateMethod then OK
6668
else if sym.owner == cls then
67-
if sym.isUpdateMethod || sym.isConstructor then OK
69+
if sym.isConstructor then OK
6870
else NotInUpdateMethod(sym, cls)
6971
else if sym.isStatic then OutsideClass(cls)
7072
else sym.owner.inExclusivePartOf(cls)

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,8 +995,12 @@ class Namer { typer: Typer =>
995995
end if
996996
}
997997

998+
/** Add an implicit Mutable flag to consume methods in Mutable classes. This
999+
* turns the method into an update method.
1000+
*/
9981001
private def normalizeFlags(denot: SymDenotation)(using Context): Unit =
999-
if denot.is(Method) && denot.hasAnnotation(defn.ConsumeAnnot) then
1002+
if denot.is(Method) && denot.hasAnnotation(defn.ConsumeAnnot)
1003+
&& denot.owner.derivesFrom(defn.Caps_Mutable) then
10001004
denot.setFlag(Mutable)
10011005

10021006
/** Intentionally left without `using Context` parameter. We need

library/src/scala/caps/package.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ type Shared = SharedCapability
6363
* During separation checking, exclusive usage of marked capabilities will be enforced.
6464
*/
6565
@experimental
66-
trait ExclusiveCapability extends Capability, Classifier
66+
trait ExclusiveCapability extends Capability
6767

6868
@experimental
6969
type Exclusive = ExclusiveCapability
@@ -80,7 +80,7 @@ trait Control extends SharedCapability, Classifier
8080

8181
/** Marker trait for classes with methods that require an exclusive reference. */
8282
@experimental
83-
trait Mutable extends ExclusiveCapability, Classifier
83+
trait Mutable extends ExclusiveCapability
8484

8585
/** Marker trait for classes with reader methods, typically extended by Mutable classes */
8686
@experimental
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
-- Error: tests/neg-custom-args/captures/classified-inheritance.scala:5:6 ----------------------------------------------
2-
5 |class C2 extends caps.Control, caps.Mutable // error
2+
5 |class C2 extends caps.Control, caps.Read // error
33
| ^
4-
| class C2 inherits two unrelated classifier traits: trait Mutable and trait Control
4+
| class C2 inherits two unrelated classifier traits: trait Read and trait Control
55
-- Error: tests/neg-custom-args/captures/classified-inheritance.scala:10:6 ---------------------------------------------
66
10 |class C3 extends Matrix, Async // error
77
| ^
8-
| class C3 inherits two unrelated classifier traits: trait Control and trait Mutable
8+
| class C3 inherits two unrelated classifier traits: trait Control and trait Read

tests/neg-custom-args/captures/classified-inheritance.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import language.experimental.captureChecking
22

33
class C1 extends caps.Control, caps.SharedCapability // OK
44

5-
class C2 extends caps.Control, caps.Mutable // error
5+
class C2 extends caps.Control, caps.Read // error
66

77
trait Async extends caps.Control
8-
class Matrix extends caps.Mutable
8+
class Matrix extends caps.Read
99

1010
class C3 extends Matrix, Async // error

tests/neg-custom-args/captures/classifiers-1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
class M extends caps.Mutable
1+
class M extends caps.Read
22

33
class M1(x: Int => Int) extends M // error
44

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
| The two sets overlap at : {a}
1515
|
1616
|where: ^ refers to a fresh root capability classified as Mutable in the type of value a
17-
| ^² refers to a fresh root capability classified as Mutable created in method test1 when checking argument to parameter x of method apply
17+
| ^² refers to a fresh root capability created in method test1 when checking argument to parameter x of method apply
1818
-- Error: tests/neg-custom-args/captures/i23726.scala:16:5 -------------------------------------------------------------
1919
16 | f3(b) // error
2020
| ^
@@ -31,7 +31,7 @@
3131
| The two sets overlap at : {b}
3232
|
3333
|where: ^ refers to a fresh root capability classified as Mutable in the type of value b
34-
| ^² refers to a fresh root capability classified as Mutable created in method test1 when checking argument to parameter x of method apply
34+
| ^² refers to a fresh root capability created in method test1 when checking argument to parameter x of method apply
3535
-- Error: tests/neg-custom-args/captures/i23726.scala:24:5 -------------------------------------------------------------
3636
24 | f7(a) // error
3737
| ^
@@ -48,4 +48,4 @@
4848
| The two sets overlap at : {a}
4949
|
5050
|where: ^ refers to a fresh root capability classified as Mutable in the type of value a
51-
| ^² refers to a fresh root capability classified as Mutable created in method test1 when checking argument to parameter x of method apply
51+
| ^² refers to a fresh root capability created in method test1 when checking argument to parameter x of method apply

tests/neg-custom-args/captures/i24310.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ class Matrix(val f: () => Int) extends Mutable:
1111
update def add(): Unit = ()
1212

1313

14-
@main def test =
14+
def test(consume proc: () => Int) =
1515
val r: Ref^ = Ref()
1616
val m: Matrix^ = Matrix(() => 42)
1717
val m2: Matrix^ = Matrix(() => m.run())
1818
val m3: Matrix^ = Matrix(() => r.get())
19+
val m4: Matrix^ = Matrix(proc)
1920

2021
def par(f1: () => Int, f2: () => Int): Unit =
2122
println(s"par results: ${f1()} and ${f2()}")

tests/neg-custom-args/captures/lazyvals-sep.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
|Note that {cap} is an exclusive capture set of the mutable type Ref^,
3535
|it cannot subsume a read-only capture set of the mutable type Ref^{TestClass.this.r.rd}.
3636
|
37-
|where: ^ and cap refer to a fresh root capability classified as Mutable created in lazy value lazyVal8 when checking argument to parameter ref of constructor Wrapper
37+
|where: ^ and cap refer to a fresh root capability created in lazy value lazyVal8 when checking argument to parameter ref of constructor Wrapper
3838
|
3939
| longer explanation available when compiling with `-explain`
4040
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazyvals-sep.scala:77:12 ---------------------------------
@@ -48,7 +48,7 @@
4848
|Note that {cap} is an exclusive capture set of the mutable type Ref^,
4949
|it cannot subsume a read-only capture set of the mutable type Ref^{TestClass.this.r.rd}.
5050
|
51-
|where: ^ and cap refer to a fresh root capability classified as Mutable created in lazy value lazyVal9 when checking argument to parameter ref of constructor Wrapper
51+
|where: ^ and cap refer to a fresh root capability created in lazy value lazyVal9 when checking argument to parameter ref of constructor Wrapper
5252
|
5353
| longer explanation available when compiling with `-explain`
5454
-- Error: tests/neg-custom-args/captures/lazyvals-sep.scala:82:8 -------------------------------------------------------

0 commit comments

Comments
 (0)