static-generics 0.1.3

Zero-cost generic statics for Rust.
Documentation
use std::marker::PhantomData;
use std::sync::atomic::{AtomicI32, Ordering};

use static_generics::{
    define_namespace, define_static,
    namespace::{Namespace, NamespaceExt},
};

define_namespace!(Test);

struct Key<T>(AtomicI32, PhantomData<T>);

// SAFETY: all-zero is a valid `AtomicI32` (0) plus `PhantomData`.
unsafe impl<T> bytemuck::Zeroable for Key<T> {}

define_static!(pub fn key<T>() -> Key<T>; in Test);

fn main() {
    let x1 = key::<i32>();
    let x2 = Test::generic_static::<Key<i32>>();
    let x3 = Test::get::<Key<i32>>();

    assert!(std::ptr::eq(x1, x2));
    assert!(std::ptr::eq(x2, x3));

    // Per-`T` isolation.
    key::<i32>().0.store(41, Ordering::Relaxed);
    key::<u32>().0.store(7, Ordering::Relaxed);
    assert_eq!(key::<i32>().0.load(Ordering::Relaxed), 41);
    assert_eq!(key::<u32>().0.load(Ordering::Relaxed), 7);

    println!("{x1:p} {x2:p} {x3:p}");
    println!("i32 slot = {}", key::<i32>().0.load(Ordering::Relaxed));
    println!("u32 slot = {}", key::<u32>().0.load(Ordering::Relaxed));
}