38 lines
1.6 KiB
Rust
38 lines
1.6 KiB
Rust
|
// 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.
|
||
|
|
||
|
|
||
|
// 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.
|