| name | rust-const |
| description | Const generics and compile-time computation expert covering const fn, type-level computation, const evaluation, MaybeUninit arrays, and compile-time validation. |
| metadata | {"triggers":["const","const generics","compile-time","const fn","MaybeUninit","type-level computation","const evaluation"]} |
Solution Patterns
Pattern 1: Basic Const Generics
struct Buffer<T, const N: usize> {
data: [T; N],
}
impl<T: Default + Copy, const N: usize> Buffer<T, N> {
fn new() -> Self {
Self {
data: [T::default(); N],
}
}
}
let buf: Buffer<u8, 1024> = Buffer::new();
Pattern 2: Const Functions
const fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0;
let mut b = 1;
let mut i = 2;
while i <= n {
let tmp = a + b;
a = b;
b = tmp;
i += 1;
}
b
}
}
}
const FIB_10: u64 = fibonacci(10);
const ARRAY: [u8; fibonacci(5) as usize] = [0; fibonacci(5) as usize];
Pattern 3: MaybeUninit for Large Arrays
use std::mem::MaybeUninit;
fn bad_large_array() -> [u8; 1024 * 1024] {
[0; 1024 * 1024]
}
fn good_large_array() -> Box<[u8; 1024 * 1024]> {
Box::new([0; 1024 * 1024])
}
fn uninit_array<const N: usize>() -> Box<[u8; N]> {
let mut data: Box<[MaybeUninit<u8>; N]> =
Box::new(unsafe { MaybeUninit::uninit().assume_init() });
for elem in &mut data[..] {
elem.write(0);
}
unsafe { Box::from_raw(Box::into_raw(data) as *mut [u8; N]) }
}
Pattern 4: Compile-Time Validation
const fn validate_config(size: usize, alignment: usize) -> bool {
size > 0 && alignment.is_power_of_two()
}
struct Config<const SIZE: usize, const ALIGN: usize> {
_phantom: PhantomData<[u8; SIZE]>,
}
impl<const SIZE: usize, const ALIGN: usize> Config<SIZE, ALIGN> {
const fn new() -> Self {
assert!(validate_config(SIZE, ALIGN), "Invalid configuration");
Self { _phantom: PhantomData }
}
}
const CONFIG: Config<1024, 8> = Config::new();
Pattern 5: Type-Level State Machine
struct Uninitialized;
struct Initialized;
struct StateMachine<State, const N: usize> {
buffer: [u8; N],
_state: PhantomData<State>,
}
impl<const N: usize> StateMachine<Uninitialized, N> {
fn new() -> Self {
Self {
buffer: [0; N],
_state: PhantomData,
}
}
fn initialize(self) -> StateMachine<Initialized, N> {
StateMachine {
buffer: self.buffer,
_state: PhantomData,
}
}
}
impl<const N: usize> StateMachine<Initialized, N> {
fn process(&mut self) {
}
}
Const Fn Capabilities
What Works in Const Fn
const fn works() {
let x = 1 + 2;
if x > 0 { }
let mut i = 0;
while i < 10 { i += 1; }
match x {
0 => {},
_ => {},
}
const fn helper() -> i32 { 42 }
let y = helper();
}
Current Limitations
const fn limitations() {
}
Workflow
Step 1: Identify Const Opportunities
Can be const if:
โ Value known at compile time
โ No heap allocation needed
โ No dynamic dispatch
โ Pure computation (no I/O)
Step 2: Choose Pattern
Need:
โ Fixed-size array? Const generic
โ Compile-time computation? Const fn
โ Large array? MaybeUninit + Box
โ Validation? Const assertion
โ Type-level state? PhantomData + const generic
Step 3: Verify Benefits
Const advantages:
โ
Zero runtime cost
โ
Compile-time validation
โ
Better optimization
โ
Smaller binary (sometimes)
Drawbacks:
โ Longer compile time
โ Limited feature set
โ Complex error messages
Review Checklist
When using const:
Verification Commands
cargo build --release
cargo asm my_module::my_const_fn
cargo check
cargo test --lib
Common Pitfalls
1. Stack Overflow
Symptom: Segmentation fault
let arr = [0u8; 1024 * 1024];
let arr = Box::new([0u8; 1024 * 1024]);
2. Uninitialized Memory
Symptom: Undefined behavior
let mut arr: [u8; 100];
println!("{}", arr[0]);
let arr = [0u8; 100];
3. Const Generic Mismatch
Symptom: Type mismatch errors
fn process<const N: usize>(data: [u8; N]) {
let other: [u8; 10] = data;
}
fn process<const N: usize>(data: [u8; N]) -> [u8; N] {
data
}
Related Skills
- rust-type-driven - Type-level programming
- rust-performance - Zero-cost abstractions
- rust-unsafe - MaybeUninit safety
- rust-macro - Compile-time code generation
Localized Reference
- Chinese version: SKILL_ZH.md - ๅฎๆดไธญๆ็ๆฌ๏ผๅ
ๅซๆๆๅ
ๅฎน