const-tools 0.1.2

Utilities to help write safe const fns such as destructuring and array operations.
Documentation
  • Coverage
  • 100%
    8 out of 8 items documented8 out of 8 items with examples
  • Size
  • Source code size: 70.47 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.22 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 18s Average build duration of successful builds.
  • all releases: 15s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • mickvangelderen/const-tools
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • mickvangelderen

const-tools

This crate provides macros that help write const functions. Please view the documentation at docs.rs/const-tools.

Motivation

Stable rust (as of Oct 2025) does not allow destructuring of tuples, structs and arrays in const contexts:

const fn into_inner<T>(wrap: (T,)) -> T {
    let (value,) = wrap;
    value
}

gives:

error[E0493]: destructor of `Wrap<T>` cannot be evaluated at compile-time

Additionally, moving values out of arrays and building new ones is tricky:

const fn wrap_all<T, const N: usize>(value: [T; N]) -> [(T,); N] {
    // Create uninitialized output array
    let mut oa: [std::mem::MaybeUninit<(T,)>; N] =
        [const { std::mem::MaybeUninit::uninit() }; N];

    // Wrap input to prevent drop
    let ia = std::mem::ManuallyDrop::new(value);
    // Get reference to inner value (Deref not available in const)
    let ia: &[T; N] = unsafe { std::mem::transmute(&ia) };

    let mut index = 0;
    while index < N {
        // Read a single item from the input array
        let item = unsafe { std::ptr::read(&ia[index]) };
        // Initialize the element in the output array
        oa[index].write((item,));
        index += 1;
    }

    // All elements have been initialized
    unsafe { std::mem::transmute_copy(&oa) }
}

This library provides macros to make all of this safe and easy.

use const_tools::{destructure, map};

const fn into_inner<T>(value: (T,)) -> T {
    destructure!(let (inner,) = value);
    inner
}

const fn wrap_all<T, const N: usize>(value: [T; N]) -> [(T,); N] {
    map!(value, |item| (item,))
}