Skip to content

Commit 67708cb

Browse files
committed
Tests for the new capture-variable syntax
1 parent ff068c6 commit 67708cb

19 files changed

+287
-1
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4086,7 +4086,7 @@ object Parsers {
40864086
* TypeDefRHS ::= Type
40874087
* | CaptureSet -- under captureChecking
40884088
*/
4089-
def typeDefOrDcl(start: Offset, mods: Modifiers): Tree = { // FIXME: ^-qualified members should automatically receive the CapSet interval!
4089+
def typeDefOrDcl(start: Offset, mods: Modifiers): Tree = {
40904090

40914091
def typeDefRHS(): Tree =
40924092
if Feature.ccEnabled && in.token == LBRACE && !isDclIntroNext then
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
4+
5+
def main() =
6+
trait Channel[T] extends caps.Capability:
7+
def send(msg: T): Unit
8+
def recv(): T
9+
10+
trait Logger extends caps.Capability:
11+
def log(msg: String): Unit
12+
13+
// we can close over anything subsumed by the 'trusted' brand capability, but nothing else
14+
def runSecure[C >: {trusted} <: {trusted}](block: () ->{C} Unit): Unit = block()
15+
16+
// This is a 'brand" capability to mark what can be mentioned in trusted code
17+
object trusted extends caps.Capability
18+
19+
val trustedLogger: Logger^{trusted} = ???
20+
val trustedChannel: Channel[String]^{trusted} = ???
21+
22+
val untrustedLogger: Logger^ = ???
23+
val untrustedChannel: Channel[String]^ = ???
24+
25+
runSecure: () =>
26+
trustedLogger.log("Hello from trusted code") // ok
27+
28+
runSecure: () =>
29+
trustedChannel.send("I can send")
30+
trustedLogger.log(trustedChannel.recv()) // ok
31+
32+
runSecure: () =>
33+
"I am pure" // ok
34+
35+
runSecure: () => // error
36+
untrustedLogger.log("I can't be used here")
37+
38+
runSecure: () => // error
39+
untrustedChannel.send("I can't be used here")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
4+
5+
def main() =
6+
trait Channel[T] extends caps.Capability:
7+
def send(msg: T): Unit
8+
def recv(): T
9+
10+
trait Logger extends caps.Capability:
11+
def log(msg: String): Unit
12+
13+
// we can close over anything subsumed by the 'trusted' brand capability, but nothing else
14+
def runSecure(block: () ->{trusted} Unit): Unit = block()
15+
16+
// This is a 'brand" capability to mark what can be mentioned in trusted code
17+
object trusted extends caps.Capability
18+
19+
val trustedLogger: Logger^{trusted} = ???
20+
val trustedChannel: Channel[String]^{trusted} = ???
21+
22+
val untrustedLogger: Logger^ = ???
23+
val untrustedChannel: Channel[String]^ = ???
24+
25+
runSecure: () =>
26+
trustedLogger.log("Hello from trusted code") // ok
27+
28+
runSecure: () =>
29+
trustedChannel.send("I can send")
30+
trustedLogger.log(trustedChannel.recv()) // ok
31+
32+
runSecure: () =>
33+
"I am pure" : Unit // ok
34+
35+
runSecure: () => // error
36+
untrustedLogger.log("I can't be used here")
37+
38+
runSecure: () => // error
39+
untrustedChannel.send("I can't be used here")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg-custom-args/captures/capset-members2.scala:5:9 -----------------------------------------------------
2+
5 | type C^[T] // error
3+
| ^
4+
| capture-set member declarations cannot have type parameters
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
4+
trait Foo:
5+
type C^[T] // error
6+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- [E095] Syntax Error: tests/neg-custom-args/captures/capset-members3.scala:5:10 --------------------------------------
2+
5 | type C^ _ // error
3+
| ^
4+
| =, >:, or <: expected, but '_' found
5+
|
6+
| longer explanation available when compiling with `-explain`
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
4+
trait Foo:
5+
type C^ _ // error
6+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import language.experimental.captureChecking
2+
import language.experimental.modularity
3+
import caps.*
4+
5+
def test =
6+
val x: Any^ = ???
7+
val y: Any^ = ???
8+
val z: Any^ = ???
9+
def onlyWithZ[C^](using c: Contains[C, z.type]) = ???
10+
11+
trait IncludesZ[C^]:
12+
val c: Contains[C, z.type]
13+
14+
trait Foo:
15+
type C >: {x} <: {x,y,z} : IncludesZ
16+
17+
val foo: Foo = ???
18+
/* new Foo {
19+
override given IncludesZ[C]: // FIXME: doesn't work yet
20+
val c: Contains[C, z.type] = summon
21+
cap type C = {x,z}
22+
} */
23+
onlyWithZ(using foo.C.c)
24+
onlyWithZ[{z}]
25+
onlyWithZ[{x,z}]
26+
onlyWithZ[{x,y,z}]
27+
onlyWithZ[{x,y}] // error
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
4+
trait Label extends Capability:
5+
type Fv^ // the capability set occurring freely in the `block` passed to `boundary` below.
6+
7+
def boundary[T, C^](block: Label{type Fv = {C} } ->{C} T): T = ??? // link label and block capture set
8+
def suspend[U](label: Label)[D^ <: {label.Fv}](handler: () ->{D} U): U = ??? // note the path
9+
10+
def test =
11+
val x = 1
12+
boundary: outer =>
13+
val y = 2
14+
boundary: inner =>
15+
val z = 3
16+
val w = suspend(outer) {() => z} // ok
17+
val v = suspend(inner) {() => y} // ok
18+
val u = suspend(inner): () =>
19+
suspend(outer) {() => y} // ok
20+
suspend(outer) {() => y} // ok
21+
y
22+
suspend(outer) { () => // error
23+
suspend(outer) {() => y }
24+
}
25+
suspend(outer): () => // error (leaks the inner label)
26+
println(inner)
27+
x + y + z
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import language.experimental.captureChecking
2+
3+
trait Ctx[T]
4+
5+
def test =
6+
val x: Any^ = ???
7+
val y: Any^ = ???
8+
object O:
9+
val z: Any^ = ???
10+
def foo[A >: {y} <: {x},
11+
B^,
12+
C^ <: {x},
13+
D^ : Ctx,
14+
E^ <: {C},
15+
F^ <: {C},
16+
G^ <: {x, y},
17+
H >: {x} <: {x,y} : Ctx, T, U]()[I^ <: {y, G, H},
18+
J^ <: {O.z},
19+
K^ <: {x, O.z},
20+
L^ <: {x, y, O.z},
21+
M^ >: {x, y, O.z} <: {C} : Ctx,
22+
N^ >: {x} <: {x},
23+
O^ >: {O.z} <: {O.z}] = ???

0 commit comments

Comments
 (0)