summaryrefslogtreecommitdiffstats
path: root/src/test/ui/print_type_sizes/niche-filling.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/print_type_sizes/niche-filling.rs')
-rw-r--r--src/test/ui/print_type_sizes/niche-filling.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
new file mode 100644
index 000000000..0716cee21
--- /dev/null
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -0,0 +1,101 @@
+// compile-flags: -Z print-type-sizes
+// build-pass
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+// FIXME: consider using an attribute instead of side-effects.
+
+// This file illustrates how niche-filling enums are handled,
+// modelled after cases like `Option<&u32>`, `Option<bool>` and such.
+//
+// It uses NonZeroU32 rather than `&_` or `Unique<_>`, because
+// the test is not set up to deal with target-dependent pointer width.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![feature(start)]
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+use std::num::NonZeroU32;
+
+pub enum MyOption<T> { None, Some(T) }
+
+#[rustc_layout_scalar_valid_range_start(0)]
+#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
+pub struct MyNotNegativeOne {
+ _i: i32,
+}
+
+impl<T> Default for MyOption<T> {
+ fn default() -> Self { MyOption::None }
+}
+
+pub enum EmbeddedDiscr {
+ None,
+ Record { pre: u8, val: NonZeroU32, post: u16 },
+}
+
+impl Default for EmbeddedDiscr {
+ fn default() -> Self { EmbeddedDiscr::None }
+}
+
+#[derive(Default)]
+pub struct IndirectNonZero {
+ pre: u8,
+ nested: NestedNonZero,
+ post: u16,
+}
+
+pub struct NestedNonZero {
+ pre: u8,
+ val: NonZeroU32,
+ post: u16,
+}
+
+impl Default for NestedNonZero {
+ fn default() -> Self {
+ NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+ }
+}
+
+pub enum Enum4<A, B, C, D> {
+ One(A),
+ Two(B),
+ Three(C),
+ Four(D)
+}
+
+pub union Union1<A: Copy> {
+ a: A,
+}
+
+pub union Union2<A: Copy, B: Copy> {
+ a: A,
+ b: B,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+ let _x: MyOption<NonZeroU32> = Default::default();
+ let _y: EmbeddedDiscr = Default::default();
+ let _z: MyOption<IndirectNonZero> = Default::default();
+ let _a: MyOption<bool> = Default::default();
+ let _b: MyOption<char> = Default::default();
+ let _c: MyOption<std::cmp::Ordering> = Default::default();
+ let _d: MyOption<MyOption<u8>> = Default::default();
+ let _e: Enum4<(), char, (), ()> = Enum4::One(());
+ let _f: Enum4<(), (), bool, ()> = Enum4::One(());
+ let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+ let _h: MyOption<MyNotNegativeOne> = Default::default();
+
+ // Unions do not currently participate in niche filling.
+ let _i: MyOption<Union2<NonZeroU32, u32>> = Default::default();
+
+ // ...even when theoretically possible.
+ let _j: MyOption<Union1<NonZeroU32>> = Default::default();
+ let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
+
+ 0
+}