Alignment by an externally defined const

The #[repr(align(N))] seems to require that N be an integer literal. In Zephyr, which I'm making Rust work with, there are arch headers that define the alignment for a given target (say for the stack), which through bindgen, ends up as a const in zephyr-sys.

Is there any way that I can make a #[repr(align(N))] work with a value that comes from a constant like this. Well, at least any way short of making my own procedural macro to do it?

1 Like

There is a trick, but it's pretty convoluted:

pub struct AlignAsStruct;

pub trait AlignAsTrait<const N: usize> {
    type Aligned;
}

macro_rules! impl_alignas {
    ( $($align:literal),* $(,)? ) => {
        $(
            const _: () = {
                #[repr(align($align))]
                pub struct Aligned;
                impl AlignAsTrait<$align> for AlignAsStruct {
                    type Aligned = Aligned;
                }
            };
        )*
    };
}
impl_alignas!(1, 2, 4, 8, 16, 32, 64, 128, 256 /* etc. */,);

#[repr(transparent)]
pub struct AlignAs<const N: usize>([<AlignAsStruct as AlignAsTrait<N>>::Aligned; 0])
where
    AlignAsStruct: AlignAsTrait<N>;

Then just include AlignAs<N> as a (first) member of your struct.

5 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.