{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreifgqri7jqbhsoolag7j2vil2doycoria4cyaspr6mc5pgqiektl2m",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mozryszddgf2"
},
"path": "/t/a-read-only-no-alias-reference/24410#post_1",
"publishedAt": "2026-06-24T08:32:59.000Z",
"site": "https://internals.rust-lang.org",
"textContent": "# Pre-RFC: Exclusive shared references for read-only noalias borrows\n\n## Summary\n\nRust currently has two main reference modes:\n\n&T // shared, read-only-ish\n\n&mut T // exclusive, mutable\n\nThis post proposes exploring a third reference mode:\n\n&^T _// exclusive, read-only_\n\nThe syntax is only a placeholder, names like &uniq T, &noalias T, or something else may be better.\n\nThe basic idea is simple: this would be a reference that is read-only like &T, but exclusive/non-overlapping like &mut T.\n\nIf rustc cannot prove that the borrow is exclusive and non-overlapping, creating the borrow should be rejected.\n\n**reasons**\n\nRust already has strong aliasing information, but today exclusivity and mutability are mostly bundled together in &mut T.\n\nSometimes a function does not want to mutate a value, but it still wants to know that the value does not alias anything else. In those cases, using &mut T works mechanically, but it communicates the wrong thing at the API level.\n\nFor example:\n\nfn compute(input: &^[f32], output: &mut [f32]) {\n\n\n *// input is read-only*\n\n *// output is mutable*\n\n *// input and output are guaranteed non-overlapping*\n\n\n}\n\nThe intent is:\n\n * input will only be read;\n * input does not overlap with output;\n * the compiler can optimize based on that exclusivity.\n\n\n\nThis is somewhat similar to C’s const T * restrict, except checked by Rust’s borrow checker instead of being trusted as an unsafe programmer promise.\n\n**Proposed semantics**\n\nFor a live &^T borrow:\n\n 1. The referenced bytes must be live, initialized, aligned, non-null, and valid for T.\n 2. The borrow may read from T.\n 3. The borrow may not write to T.\n 4. No other live reference may overlap the pointed-to bytes.\n 5. No non-derived raw pointer may read or write the pointed-to bytes while the borrow is live.\n 6. Pointers or references derived from the &^T may only read.\n 7. &^T is not Copy, because copying it would create two exclusive aliases.\n 8. &^T may be reborrowed as &T for a shorter lifetime, but the original &^T is suspended while that reborrow is live.\n 9. For DSTs and slices, the exclusivity applies to the whole dynamic byte span.\n 10. If rustc cannot prove the borrow is exclusive/non-overlapping, the program is rejected.\n\n\n\nThe intended distinction is:\n\n&T _// shared + read-only-ish_\n\n&mut T _// exclusive + mutable_\n\n&^T _// exclusive + read-only_\n\n**Interaction with**\n\n**UnsafeCell**\n\nFor the strongest optimization value, &^T should probably require that T contains no UnsafeCell, or use some kind of Freeze-like property.\n\nWithout this restriction, &^T would be read-only through the reference, but the underlying memory could still be mutated through interior mutability. That would make the optimization guarantees much weaker.\n\nSo the strongest useful version is something like:\n\n&^T where T: FreezeLike\n\nMeaning: no interior mutable bytes are reachable through this reference.\n\n**Potential LLVM lowering**\n\nAn exclusive shared reference could let rustc safely give LLVM stronger information than it can give for a normal shared reference.\n\nAt function boundaries, where valid, &^T could potentially lower to pointer arguments with attributes like:\n\nptr noalias readonly nonnull noundef align N dereferenceable(M)\n\nPossible LLVM attributes or metadata enabled by this reference kind:\n\n * noalias: the referenced memory does not alias other active accesses.\n * readonly: the function does not write through this pointer argument.\n * nonnull: references are non-null.\n * noundef: references must be valid values.\n * align N: reference alignment is known.\n * dereferenceable(M): the pointed-to span is known to be dereferenceable.\n * captures(none): when rustc can prove the pointer does not escape.\n * captures(address, read_provenance): when only limited read-only provenance can escape.\n * !alias.scope / !noalias metadata: for scoped noalias information inside function bodies, reborrows, loops, and disjoint slice/range borrows.\n * potentially memory(argmem: read) for functions or calls whose memory effects are limited to reading argument memory.\n\n\n\nFor example:\n\nfn sum(a: &^[u64], b: &^[u64]) -> u64 {\n\n\n *// ...*\n\n\n}\n\nThis could tell LLVM that:\n\n * a and b are readable;\n * neither a nor b is written through;\n * a and b do not overlap;\n * both spans are dereferenceable for their slice lengths.\n\n\n\nThat could help with vectorization, load hoisting, redundant-load elimination, and alias analysis.\n\n**Why not just use**\n\n**& mut T**\n\n**?**\n\n&mut T already provides exclusivity, but it also means mutable access at the API level.\n\nThis proposal is about separating exclusivity from mutability:\n\nexclusive + mutable => &mut T\n\nexclusive + read-only => &^T\n\nshared + read-only => &T\n\nUsing &mut T for read-only noalias access works in some cases, but it makes APIs less clear. A function that only reads from a value should not need to request mutable access just to express that the value is unique.\n\nThe goal is to allow APIs to say exactly what they mean: this memory is read-only, but it is also exclusive and non-overlapping.",
"title": "A read only no alias reference"
}