placid - Separated ownership and in-place construction
placid extends Rust's ownership model with owned and uninit references with pinning variants (semantically &own T, &uninit T, and &pin own T or Pin<&own T>). It also provides macros, traits, and functions for constructing and manipulating these types, achieving safe in-place construction.
The problem
In Rust, the ownership of a value is typically bound to the value itself. In other words, there is no way to separate the ownership of a value from it.
This creates challenges in scenarios where:
- You need to construct large values in-place to build address-aware objects ergonomically;
- You want to transfer ownership of large objects without expensive
memcpys;
Traditional Rust forces you to construct values on the stack, then move them, which can be inefficient for large types. placid solves this by introducing owned and uninit references that carry full ownership through a reference.
Features
- Owned References (
&own T): Carry exclusive ownership through a reference. - Pinned Owned References (
&pin own T): Combine ownership with pinning guarantees for immovable types. - In-place Construction: Construct complex types directly in their final location using
init!andinit_pin!macros. - Uninit References: Work safely with uninitialized memory.
- Safe Movement: Transfer ownership out of smart pointers like
Boxwithout reallocating or moving the underlying data.
Usage
Add placid to your Cargo.toml:
[]
= "<the current version>"
Basic Ownership
Constructing an owned reference directly on the stack:
use ;
let simple = own!;
assert_eq!;
// data is dropped here.
// In a real scenario, you'd construct this in-place rather than moving.
let owned = own!;
process_owned;
Pinned Types
For self-referential or pinned types:
use ;
use ;
let pinned = pown!;
process_pinned;
Moving Ownership
Moving out an owned reference from a regular smart pointer:
use ;
let boxed = Boxnew;
let mut left; // Box<MaybeUninit<String>>
// Move out an owned reference from the Box. The original
// allocation is transferred to `left`, mutably borrowed
// by `own`.
let own = into_own!;
assert_eq!;
// Drops the String, but not the Box allocation.
drop;
// Now we can reuse the Box allocation.
let right = left.write;
assert_eq!;
License
This project is licensed under either of:
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
References
moveitpin-init- The Algebra of Loans in Rust | Nadri's musings
- What is a place expression?
- The Rust official documentations