summaryrefslogtreecommitdiffstats
path: root/src/test/ui/layout/zero-sized-array-enum-niche.rs
blob: 23bbbfbfc58814a4a1c298e3193931c287825528 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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.