Skip to main content

melinoe/token/
capability.rs

1//! Sealed capability traits shared by every Melinoe token family.
2//!
3//! A *permit* is evidence, materialised in the borrow checker, that the holder
4//! may access branded data in a particular mode. Permits are produced only by
5//! the token types in this crate; the traits are [sealed] so downstream crates
6//! cannot forge a permit by implementing the trait on a foreign type.
7//!
8//! The capability lattice is intentionally tiny:
9//!
10//! ```text
11//!   WritePermit<'brand>  ⊑  ReadPermit<'brand>
12//! ```
13//!
14//! Every write permit is also a read permit; the reverse does not hold.
15//!
16//! [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html
17
18/// Crate-private supertrait used to seal the public capability traits.
19///
20/// The module is `pub(crate)`, so the trait is nameable in bounds inside this
21/// crate yet unreachable—and therefore unimplementable—from any other crate.
22pub(crate) mod private {
23    /// Sealing marker. Implemented only for the in-crate permit carriers.
24    pub trait Sealed {}
25
26    /// Sealing marker for unique brand-owning tokens.
27    pub trait BrandOwner {}
28}
29
30/// Unique brand owner whose borrows carry Melinoe's read/write permits.
31///
32/// # Safety
33///
34/// Implementors must be the sole owning token for their `'brand`, such that a
35/// shared borrow proves read access and a mutable borrow proves exclusive write
36/// access for the entire branded region.
37pub(crate) unsafe trait BrandOwner<'brand>: private::BrandOwner {}
38
39/// Evidence that the bearer may obtain a shared (`&T`) view of any
40/// [`MelinoeCell`](crate::MelinoeCell) carrying the matching `'brand`.
41///
42/// # Safety
43///
44/// This trait is `unsafe` because [`MelinoeCell`](crate::MelinoeCell) relies on
45/// implementors to uphold the brand's exclusion invariant: while *any*
46/// `ReadPermit<'brand>` value is borrowed, no `&mut` token for the same
47/// `'brand` may simultaneously exist. Every in-crate implementor discharges
48/// this obligation through the borrow checker (the permit either *is* a borrow
49/// of the unique token, or carries one in a `PhantomData`). External crates
50/// cannot implement this trait because of the private `Sealed` supertrait.
51pub unsafe trait ReadPermit<'brand>: private::Sealed {}
52
53/// Evidence that the bearer may obtain an exclusive (`&mut T`) view of any
54/// [`MelinoeCell`](crate::MelinoeCell) carrying the matching `'brand`.
55///
56/// # Safety
57///
58/// Implementors must additionally guarantee that holding a `WritePermit<'brand>`
59/// excludes every other read *and* write permit of the same brand for the
60/// duration of the borrow. In practice the only implementors are exclusive
61/// `&mut` borrows of a brand's unique owning token, which the borrow checker
62/// proves disjoint from all other token borrows.
63pub unsafe trait WritePermit<'brand>: ReadPermit<'brand> {}
64
65impl<'brand, T> private::Sealed for &T where T: BrandOwner<'brand> {}
66
67impl<'brand, T> private::Sealed for &mut T where T: BrandOwner<'brand> {}
68
69// SAFETY: every `BrandOwner` implementor represents the unique token of its
70// brand, so a shared borrow is sufficient evidence that no mutable borrow of
71// that token, and hence no write permit, coexists for the same brand.
72unsafe impl<'brand, T> ReadPermit<'brand> for &T where T: BrandOwner<'brand> {}
73
74// SAFETY: a mutable borrow of a unique `BrandOwner` token excludes all other
75// shared and mutable borrows of that token, which is exactly the brand-wide XOR
76// guarantee required for both read and write access.
77unsafe impl<'brand, T> ReadPermit<'brand> for &mut T where T: BrandOwner<'brand> {}
78unsafe impl<'brand, T> WritePermit<'brand> for &mut T where T: BrandOwner<'brand> {}