|
| 1 | +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" |
| 2 | +#![feature(rustc_attrs)] |
| 3 | +#![crate_type = "lib"] |
| 4 | + |
| 5 | +// Various tests around the behavior of zero-sized arrays and |
| 6 | +// enum niches, especially that they have coherent size and alignment. |
| 7 | + |
| 8 | +// The original problem in #99836 came from ndarray's `TryFrom` for |
| 9 | +// `SliceInfo<[SliceInfoElem; 0], Din, Dout>`, where that returns |
| 10 | +// `Result<Self, ShapeError>` ~= `Result<AlignedZST, TypeWithNiche>`. |
| 11 | +// This is a close enough approximation: |
| 12 | +#[rustc_layout(debug)] |
| 13 | +type AlignedResult = Result<[u32; 0], bool>; //~ ERROR: layout_of |
| 14 | +// The bug gave that size 1 with align 4, but the size should also be 4. |
| 15 | +// It was also using the bool niche for the enum tag, which is fine, but |
| 16 | +// after the fix, layout decides to use a direct tagged repr instead. |
| 17 | + |
| 18 | +// Here's another case with multiple ZST alignments, where we should |
| 19 | +// get the maximal alignment and matching size. |
| 20 | +#[rustc_layout(debug)] |
| 21 | +enum MultipleAlignments { //~ ERROR: layout_of |
| 22 | + Align2([u16; 0]), |
| 23 | + Align4([u32; 0]), |
| 24 | + Niche(bool), |
| 25 | +} |
| 26 | + |
| 27 | +// Tagged repr is clever enough to grow tags to fill any padding, e.g.: |
| 28 | +// 1. `T_FF` (one byte of Tag, one byte of padding, two bytes of align=2 Field) |
| 29 | +// -> `TTFF` (Tag has expanded to two bytes, i.e. like `#[repr(u16)]`) |
| 30 | +// 2. `TFF` (one byte of Tag, two bytes of align=1 Field) |
| 31 | +// -> Tag has no room to expand! |
| 32 | +// (this outcome can be forced onto 1. by wrapping Field in `Packed<...>`) |
| 33 | +#[repr(packed)] |
| 34 | +struct Packed<T>(T); |
| 35 | + |
| 36 | +#[rustc_layout(debug)] |
| 37 | +type NicheLosesToTagged = Result<[u32; 0], Packed<std::num::NonZeroU16>>; //~ ERROR: layout_of |
| 38 | +// Should get tag_encoding: Direct, size == align == 4. |
| 39 | + |
| 40 | +#[repr(u16)] |
| 41 | +enum U16IsZero { _Zero = 0 } |
| 42 | + |
| 43 | +#[rustc_layout(debug)] |
| 44 | +type NicheWinsOverTagged = Result<[u32; 0], Packed<U16IsZero>>; //~ ERROR: layout_of |
| 45 | +// Should get tag_encoding: Niche, size == align == 4. |
0 commit comments