Align a struct to alignment of another type, with recursive type

For smallvec-like data structure I need to align the wrapper struct to alignment of its content. However, the standard 0-sized array trick for this is not suitable in this case:

struct Wrapper<T> {
    align: [T; 0],
}

because it makes impossible to use this struct in a recursive type:

struct Wrapper<T> {
    // align: [T; 0], // prevents recursive types
    // phantom: PhantomData<T>, // doesn't align
}

enum Recursive {
    A(Wrapper<Recursive>),
    B,
}

Is there another method to copy alignment of an arbitrary type? This needs to be sound for large alignments too.

1 Like

No, there is no other way to automatically copy the alignment of a type. I tried it with feature(const_generics, const_evaluatable_unchecked) Rust Playground, but no dice.

error message
error[E0391]: cycle detected when simplifying constant for the type system `std::intrinsics::min_align_of`
    |
    = note: ...which requires computing layout of `Recursive`...
    = note: ...which requires computing layout of `Wrapper<Recursive>`...
    = note: ...which requires normalizing `<Aligner<{std::mem::align_of::<T>()}> as AlignTo>::Align`...
note: ...which requires simplifying constant for the type system `Wrapper::align::{constant#0}`...
   --> src/lib.rs:9:21
    |
9   |     align: <Aligner<{std::mem::align_of::<T>()}> as AlignTo>::Align,
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `Wrapper::align::{constant#0}`...
   --> src/lib.rs:9:21
    |
9   |     align: <Aligner<{std::mem::align_of::<T>()}> as AlignTo>::Align,
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `Wrapper::align::{constant#0}`...
   --> src/lib.rs:9:21
    |
9   |     align: <Aligner<{std::mem::align_of::<T>()}> as AlignTo>::Align,
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires simplifying constant for the type system `std::intrinsics::min_align_of`, completing the cycle
note: cycle used when const-evaluating + checking `Wrapper::{constant#0}`
   --> src/lib.rs:7:13
    |
7   |     Aligner<{std::mem::align_of::<T>()}>: AlignTo
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^

It doesn't look like this will be possible without substantial changes to how alignment is calculated.

2 Likes

I've found an existing feature request for this

2 Likes