Skip to content

Commit 0817e43

Browse files
committed
Polishings
1 parent 0e6958f commit 0817e43

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

docs/_docs/reference/experimental/cc.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,8 @@ currently in development.
779779

780780
Finally, analogously to type parameters, we can lower- and upper-bound capability parameters where the bounds consist of concrete capture sets:
781781
```scala
782-
// We can close over anything subsumed branded by the 'trusted' capability, but nothing else
782+
def main() =
783+
// We can close over anything branded by the 'trusted' capability, but nothing else
783784
def runSecure[cap C >: {trusted} <: {trusted}](block: () ->{C} Unit): Unit = ...
784785

785786
// This is a 'brand" capability to mark what can be mentioned in trusted code
@@ -806,7 +807,12 @@ Finally, analogously to type parameters, we can lower- and upper-bound capabilit
806807
untrustedChannel.send("I can't be used") // error
807808
```
808809
The idea is that every capability derived from the marker capability `trusted` (and only those) are eligible to be used in the `block` closure
809-
passed to `runSecure`. We can enforce this by an explicit capability parameter `C` constraining the possible captures of `block` to the interval `>: {trusted} <: {trusted}`
810+
passed to `runSecure`. We can enforce this by an explicit capability parameter `C` constraining the possible captures of `block` to the interval `>: {trusted} <: {trusted}`.
811+
812+
Note that since capabilities of function types are covariant, we could have equivalently specified `runSecure`'s signature using implicit capture polymorphism to achieve the same behavior:
813+
```scala
814+
def runSecure(block: () ->{trusted} Unit): Unit
815+
```
810816

811817
## Capability Members
812818

@@ -828,7 +834,8 @@ trait Thread:
828834
trait GPUThread extends Thread:
829835
cap type Cap >: {cudaMalloc, cudaFree} <: {caps.cap}
830836
```
831-
837+
Since `caps.cap` is the top element for subcapturing, we could have also left out the
838+
upper bound: `cap type Cap >: {cudaMalloc, cudaFree}`.
832839

833840
We conclude with a more advanced example, showing how capability members and paths to these members can prevent leakage
834841
of labels for lexically-delimited control operators:
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: () =>
36+
untrustedLogger.log("I can't be used here") // error
37+
38+
runSecure: () =>
39+
untrustedChannel.send("I can't be used here") // error

0 commit comments

Comments
 (0)