const-util 2.3.0

Stable implementations for some missing const functions
Documentation
use core::mem::MaybeUninit;

use crate::Const;
use generic_upper_bound as gub;

mod gen {
    include!(concat!(env!("OUT_DIR"), "/for_each_align.rs"));
    pub(crate) use for_each_align;
}
pub(crate) use gen::for_each_align;

/// # Safety
/// After promoting the bytes of `C::Type` in a sufficiently aligned [`MaybeUninit`] buffer,
/// it must be valid to cast the result to `&'a C::Type`. In particular,
/// `C::Type` must not contain interior mutability.
///
/// # Examples
/// Correct usage:
/// ```
/// struct Value;
/// impl const_util::Const for Value {
///     type Type = i32;
///     const VALUE: Self::Type = 1;
/// }
/// let promoted = unsafe { const_util::promote::promote::<Value>() };
/// assert_eq!(promoted, &1);
/// ```
///
/// Incorrect usage:
/// ```ignore
/// struct Value;
/// impl const_util::Const for Value {
///     type Type = std::cell::Cell<i32>;
///     const VALUE: Self::Type = std::cell::Cell::new(1);
/// }
/// // UNDEFINED BEHAVIOR, even if unused
/// let _promoted = unsafe { const_util::promote::promote::<Value>() };
/// ```
pub const unsafe fn promote<'a, C: Const>() -> &'a C::Type {
    // SAFETY:
    // The value was written to the first `size_of::<T>()` (MaybeUninit) bytes of the object,
    // which is contained in a `SIZE >= size_of::<T>()` length MaybeUninit array at the start
    // of the object, which can be casted back to `&'a T` by safety requirements. Sufficient
    // alignment is also ensured.
    unsafe { &*core::ptr::from_ref(gub::eval_with_upper_bound::<Promote<C>>()).cast() }
}

trait Anything {}
impl<T> Anything for T {}

struct Promote<C>(C);
impl<C: Const> gub::AcceptUpperBound for Promote<C> {
    type Output = &'static dyn Anything;
    const DESIRED_GENERIC: usize = size_of::<C::Type>();
    type Eval<const UPPER: usize> = PromoteSized<C, UPPER>;
}

#[repr(C)]
struct AlignedBuf<Aligner, const SIZE: usize>([MaybeUninit<u8>; SIZE], Aligner);

struct PromoteSized<C, const SIZE: usize>(C);
impl<C: Const, const SIZE: usize> Const for PromoteSized<C, SIZE> {
    type Type = &'static dyn Anything;
    const VALUE: Self::Type = if gub::get_upper_bound::<Promote<C>>() == SIZE {
        const fn const_to_buf<C: Const, const SIZE: usize>() -> [MaybeUninit<u8>; SIZE] {
            use core::mem::ManuallyDrop;

            #[repr(C)]
            union Transmute<T, const SIZE: usize> {
                val: ManuallyDrop<T>,
                buf: [MaybeUninit<u8>; SIZE],
            }

            // SAFETY: This reads the first `min(SIZE, size_of::<T>())` bytes from T, leaving the rest
            // uninitialized. MaybeUninit<u8> can hold arbitrary data, so this is valid.
            unsafe {
                Transmute {
                    val: ManuallyDrop::new(crate::value_of::<C>()),
                }
                .buf
            }
        }
        macro_rules! handle_aligns {
            ($($align:literal)*) => {
                $(if align_of::<C::Type>() == $align {
                    #[repr(align($align))]
                    struct Aligner;
                    &AlignedBuf(const_to_buf::<C, SIZE>(), Aligner)
                } else )* {
                    panic!("Unknown alignment")
                }
            };
        }
        for_each_align!(handle_aligns)
    } else {
        &()
    };
}

#[test]
fn promote_adt() {
    #[repr(align(256))]
    #[derive(PartialEq, Eq, Debug)]
    struct Inner([u32; 3]);

    #[repr(C)]
    #[derive(PartialEq, Eq, Debug)]
    struct Composite {
        f: Option<[fn() -> i32; 3]>,
        a: Inner,
        r: &'static u32,
        p: *const u32,
        b: bool,
    }

    fn f<const N: i32>() -> i32 {
        N
    }

    struct Value;
    impl Const for Value {
        type Type = Composite;
        const VALUE: Self::Type = Composite {
            f: Some([f::<1>, f::<420>, f::<13>]),
            a: Inner([3, 2, 1]),
            r: &1,
            p: std::ptr::without_provenance(42),
            b: true,
        };
    }

    // SAFETY: A MaybeUninit buffer can hold an instance of `Composite`,
    // including provenance. It does not contain interior mutability.
    let promoted = unsafe { promote::<Value>() };

    assert_eq!(&Value::VALUE, promoted);
}