Expand description
Use a runtime u64 as a const N: u64, safely.
Const generics in Rust have to be known at compile time. That’s
frustrating when the value you actually want to parameterize on
(a modulus, a buffer size, a feature flag) only becomes known at
runtime. The orthodox workarounds are to drop the const generic
(and lose the type safety), or to write a giant match by hand.
This crate is the giant match, generated for you, with three
progressively more powerful APIs on top.
Everything is #![deny(unsafe_code)]. There is no vtable
fabrication, no transmute, no UB. The dispatch is a flat 256-arm
match that the compiler optimizes well. The tradeoff: the runtime
value must lie in 0..=255 per dispatch (and the trait this crate
ships with is just one example; you can build your own with a wider
range). For the full safety analysis and why we chose this over the
original “fabricate a vtable” approach, see DESIGN.md.
§Three APIs, in order of power
§1. reify_const / reify!
Smallest surface area. You get a &dyn HasModulus whose
modulus() returns your runtime value. The
const generic is “real” inside the dispatch (each arm calls
Modular::<N>::new()), but you can only see it through the
HasModulus trait. Useful for testing the wiring.
use const_reify::{reify_const, HasModulus};
let result = reify_const(17, |m| m.modulus());
assert_eq!(result, 17);§2. reify_nat_fn / reify_nat2_fn
When you only need the runtime value as a plain u64 inside the
callback (no const generic gymnastics needed). The closure form is
the easiest entry point and is enough for most ad-hoc uses.
use const_reify::reify_nat_fn;
let squared = reify_nat_fn(12, |n| n * n);
assert_eq!(squared, 144);§3. NatCallback / reify_nat
The full power form. Implement NatCallback on a type, and inside
call::<const N: u64>() the value N is a
genuine const generic that you can use in const N: u64 positions.
use const_reify::nat_reify::{NatCallback, reify_nat};
struct Square;
impl NatCallback<u64> for Square {
fn call<const N: u64>(&self) -> u64 { N * N }
}
assert_eq!(reify_nat(7, &Square), 49);For traits with multiple const-generic methods, the
#[reifiable] proc macro
generates the NatCallback plumbing automatically. See
Guide 4.
§See also
docs/phase5-const-reify.mdfor the design rationale, including why the range is 256 and why this is fully safe despite the “vtable fabrication” reputation of the underlying technique.- The narrative blog post for a worked example using modular arithmetic.
Re-exports§
pub use nat_reify::reify_nat;pub use nat_reify::reify_nat2;pub use nat_reify::reify_nat2_fn;pub use nat_reify::reify_nat_fn;pub use nat_reify::FnNat;pub use nat_reify::FnNat2;pub use nat_reify::Nat2Callback;pub use nat_reify::NatCallback;
Modules§
- nat_
reify - True value→type reification for natural numbers.
Macros§
- def_
nat2_ callback - Define a
Nat2Callbackstruct with minimal boilerplate. - def_
nat_ callback - Define a
NatCallbackstruct with minimal boilerplate. - reify
- Convenience macro for runtime-to-const-generic dispatch.
Structs§
- Modular
- A const-generic type parameterized by a
u64modulus.
Constants§
- MAX_
REIFY_ VALUE - Maximum supported value for
reify_constdispatch.
Traits§
- HasModulus
- Trait providing access to the const-generic modulus value.
Functions§
- reify_
const - Dispatch a runtime
u64value to the correspondingModular<N>monomorphization, passing it tofas a&dyn HasModulus.