| Crates.io | manually-static |
| lib.rs | manually-static |
| version | 1.2.0 |
| created_at | 2025-06-04 11:23:16.094682+00 |
| updated_at | 2025-06-12 18:05:33.44439+00 |
| description | Provides `ManualStatic` that is a wrapper which allows to manually manage `'static` lifetimes. It is unsafe but with `debug_assertions` it panics when the usage is wrong. |
| homepage | |
| repository | https://github.com/orengine/manually-static |
| max_upload_size | |
| id | 1700136 |
| size | 24,359 |
'static Gap with Debug-Time SafetyThis crate provides ManuallyStatic<T>,
a powerful wrapper that allows you to manually manage 'static lifetimes for your data.
While it uses unsafe under the hood, it also uses robust debug-time checks that panic on incorrect usage.
This means you can confidently assert 'static guarantees in your code,
knowing that misuse will be caught during development and testing.
manually-static?In concurrent programming with threads or asynchronous operations, data often needs to be 'static to
be shared or moved across task boundaries.
However, sometimes you have a logical
guarantee that a reference will live for the entire program's duration,
even if you can't easily prove it to the compiler through standard means.
manually-static empowers you to:
Opt-in to manual 'static management: Take control when the compiler's strictness becomes a hurdle.
Catch errors early: Leverage debug_assertions to detect use-after-free scenarios or other incorrect
dereferencing before they become hard-to-debug runtime crashes in production.
Simplify complex lifetime annotations: Reduce boilerplate and make your code more readable in scenarios
where 'static is implicitly guaranteed.
First, add manually-static to your Cargo.toml:
[dependencies]
manually-static = "1.1.2" # Or the latest version
'static need)use manually_static::ManuallyStatic;
use std::thread;
use std::time::Duration;
struct AppConfig {
version: String,
}
fn main() {
let config = ManuallyStatic::new(AppConfig {
version: String::from("1.0.0"),
});
// Get a 'static reference to the config.
// This is where ManuallyStatic shines, allowing us to pass
// a reference that the compiler would normally complain about
// without complex ownership transfers or Arc for simple reads.
let config_ref = config.get_ref();
let handle = thread::spawn(move || {
// In this thread, we can safely access the config via the 'static reference.
// In debug builds, if `config` (the original ManuallyStatic) was dropped
// before this thread accessed it, it would panic.
thread::sleep(Duration::from_millis(100)); // Simulate some work
println!("Thread: App Version: {}", config_ref.version);
});
handle.join().unwrap();
// config is dropped here after the thread has finished
}
use manually_static::ManuallyStaticPtr;
use std::sync::Mutex;
use std::array;
const N: usize = 10280;
const PAR: usize = 16;
#[allow(dead_code, reason = "It is an example.")]
struct Pool(Mutex<([Vec<u8>; N], usize)>);
fn main() {
let pool = ManuallyStaticPtr::new(Pool(Mutex::new((array::from_fn(|_| Vec::new()), 0))));
let mut joins = Vec::with_capacity(PAR);
for _ in 0..PAR {
#[allow(unused_variables, reason = "It is an example.")]
let pool = pool.clone();
joins.push(std::thread::spawn(move || {
/* ... do some work ... */
}));
}
for join in joins {
join.join().unwrap();
}
unsafe { pool.free(); }
}
unsafe under the hood: While manually-static provides debug-time checks,
the underlying mechanism involves raw pointers.
In release builds, these checks are absent,
and misusing ManuallyStaticRef after the original ManuallyStatic has been dropped
will lead to undefined behavior (UB).manually-static is your trusty companion for those tricky 'static lifetime puzzles,
offering a powerful blend of flexibility and debug-time safety!