summaryrefslogtreecommitdiffstats
path: root/tests/ui/print_type_sizes
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/print_type_sizes')
-rw-r--r--tests/ui/print_type_sizes/anonymous.rs23
-rw-r--r--tests/ui/print_type_sizes/async.rs11
-rw-r--r--tests/ui/print_type_sizes/async.stdout34
-rw-r--r--tests/ui/print_type_sizes/generator.rs18
-rw-r--r--tests/ui/print_type_sizes/generator.stdout10
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.rs23
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.stdout11
-rw-r--r--tests/ui/print_type_sizes/generics.rs51
-rw-r--r--tests/ui/print_type_sizes/generics.stdout14
-rw-r--r--tests/ui/print_type_sizes/multiple_types.rs13
-rw-r--r--tests/ui/print_type_sizes/multiple_types.stdout10
-rw-r--r--tests/ui/print_type_sizes/niche-filling.rs97
-rw-r--r--tests/ui/print_type_sizes/niche-filling.stdout112
-rw-r--r--tests/ui/print_type_sizes/no_duplicates.rs19
-rw-r--r--tests/ui/print_type_sizes/no_duplicates.stdout2
-rw-r--r--tests/ui/print_type_sizes/packed.rs59
-rw-r--r--tests/ui/print_type_sizes/packed.stdout31
-rw-r--r--tests/ui/print_type_sizes/padding.rs28
-rw-r--r--tests/ui/print_type_sizes/padding.stdout23
-rw-r--r--tests/ui/print_type_sizes/repr-align.rs32
-rw-r--r--tests/ui/print_type_sizes/repr-align.stdout16
-rw-r--r--tests/ui/print_type_sizes/repr_int_c.rs19
-rw-r--r--tests/ui/print_type_sizes/repr_int_c.stdout12
-rw-r--r--tests/ui/print_type_sizes/uninhabited.rs13
-rw-r--r--tests/ui/print_type_sizes/uninhabited.stdout6
-rw-r--r--tests/ui/print_type_sizes/variants.rs18
-rw-r--r--tests/ui/print_type_sizes/variants.stdout10
-rw-r--r--tests/ui/print_type_sizes/zero-sized-fields.rs43
-rw-r--r--tests/ui/print_type_sizes/zero-sized-fields.stdout16
29 files changed, 774 insertions, 0 deletions
diff --git a/tests/ui/print_type_sizes/anonymous.rs b/tests/ui/print_type_sizes/anonymous.rs
new file mode 100644
index 000000000..2b008ca3b
--- /dev/null
+++ b/tests/ui/print_type_sizes/anonymous.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes
+// build-pass
+
+// All of the types that occur in this function are uninteresting, in
+// that one cannot control the sizes of these types with the same sort
+// of enum-variant manipulation tricks.
+
+#![feature(start)]
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+ let _byte: u8 = 0;
+ let _word: usize = 0;
+ let _tuple: (u8, usize)= (0, 0);
+ let _array: [u8; 128] = [0; 128];
+ let _fn: fn (u8) -> u8 = id;
+ let _diverging: fn (u8) -> ! = bye;
+
+ fn id(x: u8) -> u8 { x };
+ fn bye(_: u8) -> ! { loop { } }
+
+ 0
+}
diff --git a/tests/ui/print_type_sizes/async.rs b/tests/ui/print_type_sizes/async.rs
new file mode 100644
index 000000000..1598b0696
--- /dev/null
+++ b/tests/ui/print_type_sizes/async.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// edition:2021
+// build-pass
+// ignore-pass
+
+async fn wait() {}
+
+pub async fn test(arg: [u8; 8192]) {
+ wait().await;
+ drop(arg);
+}
diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout
new file mode 100644
index 000000000..6e47bb493
--- /dev/null
+++ b/tests/ui/print_type_sizes/async.stdout
@@ -0,0 +1,34 @@
+print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Suspend0`: 16385 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size field `.arg`: 8192 bytes
+print-type-size field `.__awaitee`: 1 bytes
+print-type-size variant `Unresumed`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size field `.value`: 8192 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 8192 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 8192 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Ready`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Pending`: 0 bytes
diff --git a/tests/ui/print_type_sizes/generator.rs b/tests/ui/print_type_sizes/generator.rs
new file mode 100644
index 000000000..d1cd36274
--- /dev/null
+++ b/tests/ui/print_type_sizes/generator.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+// ignore-pass
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Return = ()> {
+ move |()| {
+ yield ();
+ let _ = array;
+ }
+}
+
+pub fn foo() {
+ let _ = generator([0; 8192]);
+}
diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/generator.stdout
new file mode 100644
index 000000000..28d4a6e6c
--- /dev/null
+++ b/tests/ui/print_type_sizes/generator.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.rs b/tests/ui/print_type_sizes/generator_discr_placement.rs
new file mode 100644
index 000000000..1a85fe95b
--- /dev/null
+++ b/tests/ui/print_type_sizes/generator_discr_placement.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// build-pass
+// ignore-pass
+
+// Tests a generator that has its discriminant as the *final* field.
+
+// Avoid emitting panic handlers, like the rest of these tests...
+#![feature(generators)]
+
+pub fn foo() {
+ let a = || {
+ {
+ let w: i32 = 4;
+ yield;
+ drop(w);
+ }
+ {
+ let z: i32 = 7;
+ yield;
+ drop(z);
+ }
+ };
+}
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout
new file mode 100644
index 000000000..7f8f4ccae
--- /dev/null
+++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout
@@ -0,0 +1,11 @@
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Suspend0`: 7 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Suspend1`: 7 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.z`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
diff --git a/tests/ui/print_type_sizes/generics.rs b/tests/ui/print_type_sizes/generics.rs
new file mode 100644
index 000000000..05097087d
--- /dev/null
+++ b/tests/ui/print_type_sizes/generics.rs
@@ -0,0 +1,51 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// 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 generics are handled: types have to be
+// monomorphized, in the MIR of the original function in which they
+// occur, to have their size reported.
+
+#[derive(Copy, Clone)]
+pub struct Pair<T> {
+ _car: T,
+ _cdr: T,
+}
+
+impl<T> Pair<T> {
+ fn new(a: T, d: T) -> Self {
+ Pair {
+ _car: a,
+ _cdr: d,
+ }
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub struct ZeroSized;
+
+impl SevenBytes {
+ fn new() -> Self { SevenBytes([0; 7]) }
+}
+
+impl FiftyBytes {
+ fn new() -> Self { FiftyBytes([0; 50]) }
+}
+
+pub fn f1<T:Copy>(x: T) {
+ let _v: Pair<T> = Pair::new(x, x);
+ let _v2: Pair<FiftyBytes> =
+ Pair::new(FiftyBytes::new(), FiftyBytes::new());
+}
+
+pub fn start() {
+ let _b: Pair<u8> = Pair::new(0, 0);
+ let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
+ let ref _z: ZeroSized = ZeroSized;
+ f1::<SevenBytes>(SevenBytes::new());
+}
diff --git a/tests/ui/print_type_sizes/generics.stdout b/tests/ui/print_type_sizes/generics.stdout
new file mode 100644
index 000000000..0f02f3979
--- /dev/null
+++ b/tests/ui/print_type_sizes/generics.stdout
@@ -0,0 +1,14 @@
+print-type-size type: `Pair<FiftyBytes>`: 100 bytes, alignment: 1 bytes
+print-type-size field `._car`: 50 bytes
+print-type-size field `._cdr`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `Pair<SevenBytes>`: 14 bytes, alignment: 1 bytes
+print-type-size field `._car`: 7 bytes
+print-type-size field `._cdr`: 7 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size type: `Pair<u8>`: 2 bytes, alignment: 1 bytes
+print-type-size field `._car`: 1 bytes
+print-type-size field `._cdr`: 1 bytes
+print-type-size type: `ZeroSized`: 0 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/multiple_types.rs b/tests/ui/print_type_sizes/multiple_types.rs
new file mode 100644
index 000000000..915903892
--- /dev/null
+++ b/tests/ui/print_type_sizes/multiple_types.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+
+// This file illustrates that when multiple structural types occur in
+// a function, every one of them is included in the output.
+
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+ Small(SevenBytes),
+ Large(FiftyBytes),
+}
diff --git a/tests/ui/print_type_sizes/multiple_types.stdout b/tests/ui/print_type_sizes/multiple_types.stdout
new file mode 100644
index 000000000..641188154
--- /dev/null
+++ b/tests/ui/print_type_sizes/multiple_types.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Large`: 50 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size variant `Small`: 7 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs
new file mode 100644
index 000000000..5e620f248
--- /dev/null
+++ b/tests/ui/print_type_sizes/niche-filling.rs
@@ -0,0 +1,97 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// 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(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: unsafe { NonZeroU32::new_unchecked(1) }, 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,
+}
+
+pub fn test() {
+ 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();
+}
diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout
new file mode 100644
index 000000000..d1753c26c
--- /dev/null
+++ b/tests/ui/print_type_sizes/niche-filling.stdout
@@ -0,0 +1,112 @@
+print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes
+print-type-size field `.nested`: 8 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size end padding: 1 bytes
+print-type-size type: `MyOption<IndirectNonZero>`: 12 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 12 bytes
+print-type-size field `.0`: 12 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Record`: 7 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size field `.val`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, u32>>`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
+print-type-size field `.val`: 4 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size end padding: 1 bytes
+print-type-size type: `Enum4<(), char, (), ()>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Two`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `One`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Three`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Four`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size type: `MyNotNegativeOne`: 4 bytes, alignment: 4 bytes
+print-type-size field `._i`: 4 bytes
+print-type-size type: `MyOption<MyNotNegativeOne>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `Union1<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union1`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union2`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, u32>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Union2`: 4 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
+print-type-size variant `Four`: 2 bytes
+print-type-size field `.0`: 2 bytes
+print-type-size variant `One`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Two`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Three`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size type: `MyOption<MyOption<u8>>`: 2 bytes, alignment: 1 bytes
+print-type-size variant `Some`: 2 bytes
+print-type-size field `.0`: 2 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<u8>`: 2 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Some`: 1 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `Enum4<(), (), bool, ()>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `Three`: 1 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size variant `One`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Two`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Four`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size type: `MyOption<bool>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `Some`: 1 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `MyOption<std::cmp::Ordering>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `Some`: 1 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `std::cmp::Ordering`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Less`: 0 bytes
+print-type-size variant `Equal`: 0 bytes
+print-type-size variant `Greater`: 0 bytes
diff --git a/tests/ui/print_type_sizes/no_duplicates.rs b/tests/ui/print_type_sizes/no_duplicates.rs
new file mode 100644
index 000000000..2ec5d9e64
--- /dev/null
+++ b/tests/ui/print_type_sizes/no_duplicates.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// 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 that when the same type occurs repeatedly
+// (even if multiple functions), it is only printed once in the
+// print-type-sizes output.
+
+pub struct SevenBytes([u8; 7]);
+
+pub fn f1() {
+ let _s: SevenBytes = SevenBytes([0; 7]);
+}
+
+pub fn test() {
+ let _s: SevenBytes = SevenBytes([0; 7]);
+}
diff --git a/tests/ui/print_type_sizes/no_duplicates.stdout b/tests/ui/print_type_sizes/no_duplicates.stdout
new file mode 100644
index 000000000..50180f356
--- /dev/null
+++ b/tests/ui/print_type_sizes/no_duplicates.stdout
@@ -0,0 +1,2 @@
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
diff --git a/tests/ui/print_type_sizes/packed.rs b/tests/ui/print_type_sizes/packed.rs
new file mode 100644
index 000000000..5ddfe4bf4
--- /dev/null
+++ b/tests/ui/print_type_sizes/packed.rs
@@ -0,0 +1,59 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// 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 packing is handled; it should cause
+// the elimination of padding that would normally be introduced
+// to satisfy alignment desirata.
+//
+// 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.
+
+#![allow(dead_code)]
+
+#[derive(Default)]
+#[repr(packed)]
+pub struct Packed1 {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+pub struct Packed2 {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+#[repr(C)]
+pub struct Packed2C {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
+
+#[derive(Default)]
+pub struct Padded {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
diff --git a/tests/ui/print_type_sizes/packed.stdout b/tests/ui/print_type_sizes/packed.stdout
new file mode 100644
index 000000000..58e1bac9e
--- /dev/null
+++ b/tests/ui/print_type_sizes/packed.stdout
@@ -0,0 +1,31 @@
+print-type-size type: `Packed2C`: 12 bytes, alignment: 2 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size padding: 1 bytes
+print-type-size field `.h`: 2 bytes
+print-type-size field `.d`: 1 bytes
+print-type-size end padding: 1 bytes
+print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.h`: 2 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size field `.d`: 1 bytes
+print-type-size end padding: 2 bytes
+print-type-size type: `Packed1`: 10 bytes, alignment: 1 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size field `.h`: 2 bytes
+print-type-size field `.d`: 1 bytes
+print-type-size type: `Packed2`: 10 bytes, alignment: 2 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.h`: 2 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size field `.d`: 1 bytes
diff --git a/tests/ui/print_type_sizes/padding.rs b/tests/ui/print_type_sizes/padding.rs
new file mode 100644
index 000000000..f41c677dc
--- /dev/null
+++ b/tests/ui/print_type_sizes/padding.rs
@@ -0,0 +1,28 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+
+// This file illustrates how padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// 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.
+
+#![allow(dead_code)]
+
+struct S {
+ a: bool,
+ b: bool,
+ g: i32,
+}
+
+enum E1 {
+ A(i32, i8),
+ B(S),
+}
+
+enum E2 {
+ A(i8, i32),
+ B(S),
+}
diff --git a/tests/ui/print_type_sizes/padding.stdout b/tests/ui/print_type_sizes/padding.stdout
new file mode 100644
index 000000000..9afdf7624
--- /dev/null
+++ b/tests/ui/print_type_sizes/padding.stdout
@@ -0,0 +1,23 @@
+print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `B`: 11 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size variant `A`: 7 bytes
+print-type-size field `.1`: 1 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `B`: 11 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size variant `A`: 7 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.1`: 4 bytes, alignment: 4 bytes
+print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size end padding: 2 bytes
diff --git a/tests/ui/print_type_sizes/repr-align.rs b/tests/ui/print_type_sizes/repr-align.rs
new file mode 100644
index 000000000..0bd11ebc9
--- /dev/null
+++ b/tests/ui/print_type_sizes/repr-align.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// 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 padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// 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.
+
+#![allow(dead_code)]
+
+#[repr(align(16))]
+#[derive(Default)]
+struct A(i32);
+
+enum E {
+ A(i32),
+ B(A)
+}
+
+#[derive(Default)]
+pub struct S {
+ a: i32,
+ b: i32,
+ c: A,
+ d: i8,
+}
diff --git a/tests/ui/print_type_sizes/repr-align.stdout b/tests/ui/print_type_sizes/repr-align.stdout
new file mode 100644
index 000000000..33671bd8e
--- /dev/null
+++ b/tests/ui/print_type_sizes/repr-align.stdout
@@ -0,0 +1,16 @@
+print-type-size type: `E`: 32 bytes, alignment: 16 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `B`: 28 bytes
+print-type-size padding: 12 bytes
+print-type-size field `.0`: 16 bytes, alignment: 16 bytes
+print-type-size variant `A`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size type: `S`: 32 bytes, alignment: 16 bytes
+print-type-size field `.c`: 16 bytes
+print-type-size field `.a`: 4 bytes
+print-type-size field `.b`: 4 bytes
+print-type-size field `.d`: 1 bytes
+print-type-size end padding: 7 bytes
+print-type-size type: `A`: 16 bytes, alignment: 16 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size end padding: 12 bytes
diff --git a/tests/ui/print_type_sizes/repr_int_c.rs b/tests/ui/print_type_sizes/repr_int_c.rs
new file mode 100644
index 000000000..6b103776a
--- /dev/null
+++ b/tests/ui/print_type_sizes/repr_int_c.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+
+// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
+// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
+
+#![allow(dead_code)]
+
+#[repr(C, u8)]
+enum ReprCu8 {
+ A(u16),
+ B,
+}
+
+#[repr(u8)]
+enum Repru8 {
+ A(u16),
+ B,
+}
diff --git a/tests/ui/print_type_sizes/repr_int_c.stdout b/tests/ui/print_type_sizes/repr_int_c.stdout
new file mode 100644
index 000000000..254b3c7a8
--- /dev/null
+++ b/tests/ui/print_type_sizes/repr_int_c.stdout
@@ -0,0 +1,12 @@
+print-type-size type: `ReprCu8`: 4 bytes, alignment: 2 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `A`: 3 bytes
+print-type-size padding: 1 bytes
+print-type-size field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size variant `B`: 1 bytes
+print-type-size type: `Repru8`: 4 bytes, alignment: 2 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `A`: 3 bytes
+print-type-size padding: 1 bytes
+print-type-size field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size variant `B`: 0 bytes
diff --git a/tests/ui/print_type_sizes/uninhabited.rs b/tests/ui/print_type_sizes/uninhabited.rs
new file mode 100644
index 000000000..86fab7b50
--- /dev/null
+++ b/tests/ui/print_type_sizes/uninhabited.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+// FIXME: consider using an attribute instead of side-effects.
+
+#![feature(never_type)]
+
+pub fn test() {
+ let _x: Option<!> = None;
+ let _y: Result<u32, !> = Ok(42);
+ let _z: Result<!, !> = loop {};
+}
diff --git a/tests/ui/print_type_sizes/uninhabited.stdout b/tests/ui/print_type_sizes/uninhabited.stdout
new file mode 100644
index 000000000..5eb5384bc
--- /dev/null
+++ b/tests/ui/print_type_sizes/uninhabited.stdout
@@ -0,0 +1,6 @@
+print-type-size type: `std::result::Result<u32, !>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Ok`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size type: `std::option::Option<!>`: 0 bytes, alignment: 1 bytes
+print-type-size variant `None`: 0 bytes
+print-type-size type: `std::result::Result<!, !>`: 0 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/variants.rs b/tests/ui/print_type_sizes/variants.rs
new file mode 100644
index 000000000..5a3020520
--- /dev/null
+++ b/tests/ui/print_type_sizes/variants.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+
+// This file illustrates two things:
+//
+// 1. Only types that appear in a monomorphized function appear in the
+// print-type-sizes output, and
+//
+// 2. For an enum, the print-type-sizes output will also include the
+// size of each variant.
+
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+ Small(SevenBytes),
+ Large(FiftyBytes),
+}
diff --git a/tests/ui/print_type_sizes/variants.stdout b/tests/ui/print_type_sizes/variants.stdout
new file mode 100644
index 000000000..641188154
--- /dev/null
+++ b/tests/ui/print_type_sizes/variants.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Large`: 50 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size variant `Small`: 7 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
diff --git a/tests/ui/print_type_sizes/zero-sized-fields.rs b/tests/ui/print_type_sizes/zero-sized-fields.rs
new file mode 100644
index 000000000..09415824d
--- /dev/null
+++ b/tests/ui/print_type_sizes/zero-sized-fields.rs
@@ -0,0 +1,43 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+// ignore-pass
+
+// At one point, zero-sized fields such as those in this file were causing
+// incorrect output from `-Z print-type-sizes`.
+
+struct S1 {
+ x: u32,
+ y: u32,
+ tag: (),
+}
+
+struct Void();
+struct Empty {}
+
+struct S5<TagW, TagZ> {
+ tagw: TagW,
+ w: u32,
+ unit: (),
+ x: u32,
+ void: Void,
+ y: u32,
+ empty: Empty,
+ z: u32,
+ tagz: TagZ,
+}
+
+pub fn test() {
+ let _s1: S1 = S1 { x: 0, y: 0, tag: () };
+
+ let _s5: S5<(), Empty> = S5 {
+ tagw: (),
+ w: 1,
+ unit: (),
+ x: 2,
+ void: Void(),
+ y: 3,
+ empty: Empty {},
+ z: 4,
+ tagz: Empty {},
+ };
+}
diff --git a/tests/ui/print_type_sizes/zero-sized-fields.stdout b/tests/ui/print_type_sizes/zero-sized-fields.stdout
new file mode 100644
index 000000000..72f59c4bb
--- /dev/null
+++ b/tests/ui/print_type_sizes/zero-sized-fields.stdout
@@ -0,0 +1,16 @@
+print-type-size type: `S5<(), Empty>`: 16 bytes, alignment: 4 bytes
+print-type-size field `.tagw`: 0 bytes
+print-type-size field `.unit`: 0 bytes
+print-type-size field `.void`: 0 bytes
+print-type-size field `.empty`: 0 bytes
+print-type-size field `.tagz`: 0 bytes
+print-type-size field `.w`: 4 bytes
+print-type-size field `.x`: 4 bytes
+print-type-size field `.y`: 4 bytes
+print-type-size field `.z`: 4 bytes
+print-type-size type: `S1`: 8 bytes, alignment: 4 bytes
+print-type-size field `.tag`: 0 bytes
+print-type-size field `.x`: 4 bytes
+print-type-size field `.y`: 4 bytes
+print-type-size type: `Empty`: 0 bytes, alignment: 1 bytes
+print-type-size type: `Void`: 0 bytes, alignment: 1 bytes