1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//! # Melinoe — branded, multi-token phantom capabilities
//!
//! `melinoe` provides zero-sized, brand-parameterised **capability tokens** that
//! encode data-access permissions and thread-synchronisation invariants in the
//! type system. It is a generalised evolution of the `GhostCell` pattern: where
//! `GhostCell` has one token per brand, Melinoe offers a *family* of tokens that
//! share a unified permit interface yet differ in cardinality and thread-safety
//! posture. The crate ships **no allocator, arena, or `GlobalAlloc`**—only the
//! compile-time machinery on which such systems can be built.
//!
//! It is designed for the **Mnemosyne** memory ecosystem, complementing its
//! ZST `AllocPolicy`, heap branding, and `Branded*` evidence types with a more
//! expressive, multi-token proof system for cross-thread handoff, branded heap
//! access, and lock-free interior mutability on validated hot paths.
//!
//! ## The model in one paragraph
//!
//! A [`brand_scope`] mints a unique [`ExclusiveToken<'brand>`](ExclusiveToken)
//! over a fresh, invariant lifetime. [`MelinoeCell<'brand, T>`](MelinoeCell)s
//! created under that brand reveal their contents only to a matching
//! [`ReadPermit`] (`&token`) or [`WritePermit`] (`&mut token`). Because the
//! whole brand is policed by the borrow checker's aliasing rules on that single
//! token, exclusive and shared access are mutually excluded *across every cell
//! in the region* with **zero runtime cost**—no flags, no atomics, no locks.
//!
//! ## Token families
//!
//! | Token | Cardinality | `Send`/`Sync` | Role |
//! |-------|-------------|---------------|------|
//! | [`ExclusiveToken`] | one per brand | both | sole owner; read + write |
//! | [`SharedReadToken`] | many (`Copy`) | both | fan-out read capability |
//! | [`ThreadLocalToken`](sync::ThreadLocalToken) | one per brand | neither | thread-confined owner |
//! | [`SyncRegionToken`](sync::SyncRegionToken) | one per brand | both | thread-portable owner |
//!
//! ## Multi-token composition
//!
//! Brands compose; melinoe exposes one primitive per axis and composes them
//! rather than shipping arity-specific variants:
//!
//! * **Multi-XOR** — *nest* [`brand_scope`] for several independent exclusion
//! domains at once. Each nested scope is a fresh, non-unifiable brand, so a
//! `&mut` into one region and a `&mut` into another are held simultaneously,
//! disjointness proven at compile time. Composition gives any arity for free —
//! no `brand_scopeN`.
//! * [`region::WriterShard`] — split one brand into disjoint sub-regions for
//! concurrent writers; [`SyncRegionToken`](sync::SyncRegionToken) moves a whole
//! brand's write capability across threads.
//! * [`reentrant::GuardedCell`] / [`reentrant::ReentrancyCell`] — gate *ambient*
//! (thread-lifetime) exclusive state: one runtime check at the boundary yields
//! a borrow-checked `&mut T` (or a fresh-brand token), with re-entry refused
//! rather than aliased.
//! * [`atomic::BrandedAtomic`] — *conditional atomics*: plain non-atomic access
//! under a [`WritePermit`] (proven-exclusive phase), atomic access under a
//! [`ReadPermit`] (shared phase). The capability selects the cost, so you pay
//! for synchronization only while sharing. [`Relaxed`], [`AcqRel`], and
//! [`SeqCst`] are ZST ordering policies for monomorphized atomic call sites.
//! * [`CellCowExt`] — conditional `Cow` at the ownership boundary: [`Borrowed`]
//! returns a zero-copy borrowed slice, [`Retained`] clones exactly once, and
//! [`RetainDecision`] covers data-dependent retain decisions through the same
//! sealed policy bodies.
//!
//! ## Quick start
//!
//! ```
//! use melinoe::{brand_scope, MelinoeCell};
//!
//! brand_scope(|mut token| {
//! let a = MelinoeCell::new(1_i32);
//! let b = MelinoeCell::new(2_i32);
//!
//! // Exclusive write: needs `&mut token`.
//! *a.borrow_mut(&mut token) += 10;
//!
//! // Shared reads: `&token` (or a copied `SharedReadToken`) reads any cell.
//! let snap = token.share();
//! assert_eq!(*a.borrow(snap) + *b.borrow(snap), 13);
//! });
//! ```
//!
//! A borrow guard can be **projected** onto a component of its payload without
//! copying and without re-presenting the permit—the branded analogue of
//! [`Ref::map`](core::cell::Ref::map). [`MelinoeMut::map_split`] further yields
//! two disjoint `&mut` projections from a single write permit:
//!
//! ```
//! use melinoe::{brand_scope, MelinoeCell, MelinoeMut};
//!
//! brand_scope(|mut token| {
//! let cell = MelinoeCell::new((0_u32, 0_u32));
//! // One write permit, two disjoint field writers, live at once.
//! let (mut a, mut b) =
//! MelinoeMut::map_split(cell.borrow_mut(&mut token), |t| (&mut t.0, &mut t.1));
//! *a = 1;
//! *b = 2;
//! drop((a, b));
//! assert_eq!(*cell.borrow(&token), (1, 2));
//! });
//! ```
//!
//! At an ownership boundary, [`CellCowExt`] makes the retain decision explicit.
//! A ZST policy gives compile-time branch elimination when the decision is
//! static:
//!
//! ```
//! #[cfg(feature = "alloc")]
//! {
//! use std::borrow::Cow;
//! use melinoe::{brand_scope, Borrowed, CellCowExt, MelinoeCell, Retained};
//!
//! brand_scope(|token| {
//! let cells: Vec<MelinoeCell<'_, u8>> = (0..4).map(MelinoeCell::new).collect();
//! assert!(matches!(cells.borrow_cow_with(&token, Borrowed), Cow::Borrowed(_)));
//! assert!(matches!(cells.borrow_cow_with(&token, Retained), Cow::Owned(_)));
//! });
//! }
//! ```
//!
//! Conditional atomics use the same idea on the synchronization side: a write
//! permit selects plain access, while a read permit selects atomic access. ZST
//! ordering policies keep common ordering contracts at the type level:
//!
//! ```
//! use core::sync::atomic::AtomicU64;
//! use melinoe::{brand_scope, BrandedAtomic, Relaxed};
//!
//! brand_scope(|mut token| {
//! let counter: BrandedAtomic<'_, AtomicU64> = BrandedAtomic::new(0);
//! counter.store_exclusive(10, &mut token);
//! let snap = token.share();
//! assert_eq!(counter.fetch_add_with(5, snap, Relaxed), 10);
//! assert_eq!(counter.load_with(snap, Relaxed), 15);
//! });
//! ```
//!
//! With `std`, [`sync::PartitionPlan`] drives scoped, disjoint multithreaded
//! writes by fixed part count, current hardware parallelism, or fixed chunk
//! size. Each worker receives one [`WriterShard`] and no runtime lock protects
//! the write path:
//!
//! ```
//! #[cfg(feature = "std")]
//! {
//! use melinoe::sync::{partition_for_each_with, PartitionPlan};
//! use melinoe::{brand_scope, MelinoeCell};
//!
//! brand_scope(|token| {
//! let mut cells: Vec<MelinoeCell<'_, usize>> =
//! (0..8).map(|_| MelinoeCell::new(0)).collect();
//!
//! partition_for_each_with(&mut cells, PartitionPlan::chunk_size(2), |start, mut shard| {
//! for (j, slot) in shard.iter_mut().enumerate() {
//! *slot = start + j;
//! }
//! });
//!
//! let snap = token.share();
//! for (index, cell) in cells.iter().enumerate() {
//! assert_eq!(*cell.borrow(snap), index);
//! }
//! });
//! }
//! ```
//!
//! The borrow checker rejects the unsound interleavings at compile time:
//!
//! ```compile_fail
//! use melinoe::{brand_scope, MelinoeCell};
//! brand_scope(|mut token| {
//! let cell = MelinoeCell::new(0_i32);
//! let w = cell.borrow_mut(&mut token); // exclusive borrow of `token`
//! let r = cell.borrow(&token); // ERROR: `token` already mutably borrowed
//! let _ = (w, r);
//! });
//! ```
//!
//! Tokens of different brands never mix. A cell's brand is *inferred from use*,
//! so the first access pins it; a later access with a foreign token is rejected:
//!
//! ```compile_fail
//! use melinoe::{brand_scope, MelinoeCell};
//! brand_scope(|t1| {
//! let cell = MelinoeCell::new(0_i32);
//! let _ = cell.borrow(&t1); // pins the cell's brand to `t1`'s region
//! brand_scope(|t2| {
//! let _ = cell.borrow(&t2); // ERROR: `t2`'s brand ≠ the cell's brand
//! });
//! });
//! ```
//!
//! ## Cargo features
//!
//! * `std` *(default)* — superset of `alloc`; enables [`sync::scope_exclusive`]
//! and other [`std::thread::scope`]-based demonstrations.
//! * `alloc` — links the `alloc` crate for heap-payload examples/tests.
//! * `nightly` — enables `doc_cfg` for precise feature-gated docs (requires a
//! nightly toolchain); reserved for future `generic_const_exprs` capability
//! sets.
//!
//! The crate is `#![no_std]` by default and uses no global allocator of its own.
extern crate alloc;
extern crate std;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;