Skip to main content

Crate const_reify

Crate const_reify 

Source
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.md for 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 Nat2Callback struct with minimal boilerplate.
def_nat_callback
Define a NatCallback struct with minimal boilerplate.
reify
Convenience macro for runtime-to-const-generic dispatch.

Structs§

Modular
A const-generic type parameterized by a u64 modulus.

Constants§

MAX_REIFY_VALUE
Maximum supported value for reify_const dispatch.

Traits§

HasModulus
Trait providing access to the const-generic modulus value.

Functions§

reify_const
Dispatch a runtime u64 value to the corresponding Modular<N> monomorphization, passing it to f as a &dyn HasModulus.