summaryrefslogtreecommitdiffstats
path: root/src/test/ui/layout/zero-sized-array-enum-niche.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/layout/zero-sized-array-enum-niche.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
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.rs45
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.