static-generics 0.1.3

Zero-cost generic statics for Rust.
Documentation
//! Slow `std`-based fallback for targets without a weak-COMDAT + `asm!` path.

extern crate std;

use core::any::TypeId;
use core::mem::MaybeUninit;
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};

fn registry() -> &'static Mutex<HashMap<TypeId, usize>> {
    static REGISTRY: OnceLock<Mutex<HashMap<TypeId, usize>>> = OnceLock::new();
    REGISTRY.get_or_init(|| Mutex::new(HashMap::new()))
}

pub(crate) fn generic_static_fallback<NS: 'static, T: 'static + bytemuck::Zeroable>() -> &'static T
{
    // SAFETY: This is dereferencing Box::leak address which should be valid
    unsafe { &*generic_static_fallback_mut::<NS, T>() }
}

pub(crate) fn generic_static_fallback_mut<NS: 'static, T: 'static + bytemuck::Zeroable>() -> *mut T
{
    let key = TypeId::of::<(NS, T)>();
    let mut slots = registry()
        .lock()
        .unwrap_or_else(|poison| poison.into_inner());
    if let Some(&addr) = slots.get(&key) {
        // SAFETY: only inserted below as the address of a leaked `Box<T>`
        // for this exact key.
        return addr as *mut T;
    }
    // SAFETY: T implements Zeroable
    let boxed: std::boxed::Box<T> =
        std::boxed::Box::new(unsafe { MaybeUninit::<T>::zeroed().assume_init() });
    let addr = std::boxed::Box::leak(boxed) as *mut T as usize;
    slots.insert(key, addr);

    addr as *mut T
}