diff options
Diffstat (limited to 'src/test/ui/layout/zero-sized-array-enum-niche.rs')
-rw-r--r-- | src/test/ui/layout/zero-sized-array-enum-niche.rs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/test/ui/layout/zero-sized-array-enum-niche.rs b/src/test/ui/layout/zero-sized-array-enum-niche.rs new file mode 100644 index 000000000..23bbbfbfc --- /dev/null +++ b/src/test/ui/layout/zero-sized-array-enum-niche.rs @@ -0,0 +1,45 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +// Various tests around the behavior of zero-sized arrays and +// enum niches, especially that they have coherent size and alignment. + +// The original problem in #99836 came from ndarray's `TryFrom` for +// `SliceInfo<[SliceInfoElem; 0], Din, Dout>`, where that returns +// `Result<Self, ShapeError>` ~= `Result<AlignedZST, TypeWithNiche>`. +// This is a close enough approximation: +#[rustc_layout(debug)] +type AlignedResult = Result<[u32; 0], bool>; //~ ERROR: layout_of +// The bug gave that size 1 with align 4, but the size should also be 4. +// It was also using the bool niche for the enum tag, which is fine, but +// after the fix, layout decides to use a direct tagged repr instead. + +// Here's another case with multiple ZST alignments, where we should +// get the maximal alignment and matching size. +#[rustc_layout(debug)] +enum MultipleAlignments { //~ ERROR: layout_of + Align2([u16; 0]), + Align4([u32; 0]), + Niche(bool), +} + +// Tagged repr is clever enough to grow tags to fill any padding, e.g.: +// 1. `T_FF` (one byte of Tag, one byte of padding, two bytes of align=2 Field) +// -> `TTFF` (Tag has expanded to two bytes, i.e. like `#[repr(u16)]`) +// 2. `TFF` (one byte of Tag, two bytes of align=1 Field) +// -> Tag has no room to expand! +// (this outcome can be forced onto 1. by wrapping Field in `Packed<...>`) +#[repr(packed)] +struct Packed<T>(T); + +#[rustc_layout(debug)] +type NicheLosesToTagged = Result<[u32; 0], Packed<std::num::NonZeroU16>>; //~ ERROR: layout_of +// Should get tag_encoding: Direct, size == align == 4. + +#[repr(u16)] +enum U16IsZero { _Zero = 0 } + +#[rustc_layout(debug)] +type NicheWinsOverTagged = Result<[u32; 0], Packed<U16IsZero>>; //~ ERROR: layout_of +// Should get tag_encoding: Niche, size == align == 4. |