#static #generic #generics

nightly generic-statics

generic statics for rust

1 unstable release

0.1.0 Apr 13, 2024

#24 in #generics

MIT/Apache

15KB
244 lines

generic-statics

This crate is experimental and might not be fully sound. Use at your own risk.

A workaround for missing generic statics in Rust.

use std::{ptr, sync::atomic::{AtomicPtr, Ordering}};

// This code doesn't work.
static A<T>: AtomicPtr<T> = AtomicPtr::new(ptr::null_mut());
let a = A::<usize>.load(Ordering::Relaxed);

With generic-statics:

use std::sync::atomic::{AtomicPtr, Ordering};
use generic_statics::{define_namespace, Namespace};

define_namespace!(Test);

// This works.
let a = Test::static_generic::<AtomicPtr<usize>>().load(Ordering::Relaxed);

Caveats

This crate is nightly only and relies on #![feature(asm_const)] (As of 2024-04-10, stabilization of that feature is blocked on feature(inline_const)).

The generic statics provided by this crate use static allocation (i.e. no dynamic allocation at runtime) and is almost zero-cost (aside from some inline asm instructions for computing the static address).

However, this crate only offers best-effort stable addresses:

use generic_statics::{define_namespace, Namespace};

define_namespace!(Test);

// This is *not* guaranteed but in most cases this will work just fine.
assert_eq!(
    Test::static_generic::<usize>() as *const _,
    Test::static_generic::<usize>() as *const _
);

The used approach relies on inline assembly to instantiate/reserve static data for each monomorphized variant of the function. Unfortunately inlining will return a different version of the data and thus will not return stable addresses. However, static_generic is marked #[inline(never)] which should provide stable addresses in most situations (Note that #[inline(never)] is just a hint to the compiler and doesn't guarantee anything).

Only "zeroable" types are allowed for now due to inline asm restrictions.

This crate only supports these targets for now:

  • macOS x86_64, aarch64
  • Linux x86_64, aarch64
  • FreeBSD x86_64, aarch64
  • Windows x86_64

No runtime deps