diff options
Diffstat (limited to 'src/test/ui/print_type_sizes')
23 files changed, 747 insertions, 0 deletions
diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs new file mode 100644 index 000000000..2b008ca3b --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs new file mode 100644 index 000000000..3ef7b60db --- /dev/null +++ b/src/test/ui/print_type_sizes/generics.rs @@ -0,0 +1,71 @@ +// 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 generics are handled: types have to be +// monomorphized, in the MIR of the original function in which they +// occur, to have their size reported. + +#![feature(start)] + +// In an ad-hoc attempt to avoid the injection of unwinding code +// (which clutters the output of `-Z print-type-sizes` with types from +// `unwind::libunwind`): +// +// * I am not using Default to build values because that seems to +// cause the injection of unwinding code. (Instead I just make `fn new` +// methods.) +// +// * Pair derive Copy to ensure that we don't inject +// unwinding code into generic uses of Pair when T itself is also +// Copy. +// +// (I suspect this reflect some naivety within the rust compiler +// itself; it should be checking for drop glue, i.e., a destructor +// somewhere in the monomorphized types. It should not matter whether +// the type is Copy.) +#[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()); +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 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()); + 0 +} diff --git a/src/test/ui/print_type_sizes/generics.stdout b/src/test/ui/print_type_sizes/generics.stdout new file mode 100644 index 000000000..0f02f3979 --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs new file mode 100644 index 000000000..f1ad27ec1 --- /dev/null +++ b/src/test/ui/print_type_sizes/multiple_types.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z print-type-sizes +// build-pass + +// This file illustrates that when multiple structural types occur in +// a function, every one of them is included in the output. + +#![feature(start)] + +pub struct SevenBytes([u8; 7]); +pub struct FiftyBytes([u8; 50]); + +pub enum Enum { + Small(SevenBytes), + Large(FiftyBytes), +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _e: Enum; + let _f: FiftyBytes; + let _s: SevenBytes; + 0 +} diff --git a/src/test/ui/print_type_sizes/multiple_types.stdout b/src/test/ui/print_type_sizes/multiple_types.stdout new file mode 100644 index 000000000..641188154 --- /dev/null +++ b/src/test/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/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 +} diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout new file mode 100644 index 000000000..d1753c26c --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs new file mode 100644 index 000000000..e45e4794a --- /dev/null +++ b/src/test/ui/print_type_sizes/no_duplicates.rs @@ -0,0 +1,23 @@ +// 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 that when the same type occurs repeatedly +// (even if multiple functions), it is only printed once in the +// print-type-sizes output. + +#![feature(start)] + +pub struct SevenBytes([u8; 7]); + +pub fn f1() { + let _s: SevenBytes = SevenBytes([0; 7]); +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _s: SevenBytes = SevenBytes([0; 7]); + 0 +} diff --git a/src/test/ui/print_type_sizes/no_duplicates.stdout b/src/test/ui/print_type_sizes/no_duplicates.stdout new file mode 100644 index 000000000..50180f356 --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs new file mode 100644 index 000000000..269cc3cc2 --- /dev/null +++ b/src/test/ui/print_type_sizes/packed.rs @@ -0,0 +1,69 @@ +// 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 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)] +#![feature(start)] + +#[derive(Default)] +#[repr(packed)] +struct Packed1 { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +#[repr(packed(2))] +struct Packed2 { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +#[repr(packed(2))] +#[repr(C)] +struct Packed2C { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +struct Padded { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _c: Packed1 = Default::default(); + let _d: Packed2 = Default::default(); + let _e: Packed2C = Default::default(); + let _f: Padded = Default::default(); + 0 +} diff --git a/src/test/ui/print_type_sizes/packed.stdout b/src/test/ui/print_type_sizes/packed.stdout new file mode 100644 index 000000000..58e1bac9e --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs new file mode 100644 index 000000000..d1acad16d --- /dev/null +++ b/src/test/ui/print_type_sizes/padding.rs @@ -0,0 +1,34 @@ +// compile-flags: -Z print-type-sizes +// 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. + +#![feature(start)] +#![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), +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 0 +} diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout new file mode 100644 index 000000000..9afdf7624 --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs new file mode 100644 index 000000000..07544935b --- /dev/null +++ b/src/test/ui/print_type_sizes/repr-align.rs @@ -0,0 +1,38 @@ +// 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 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. +#![feature(start)] +#![allow(dead_code)] + +#[repr(align(16))] +#[derive(Default)] +struct A(i32); + +enum E { + A(i32), + B(A) +} + +#[derive(Default)] +struct S { + a: i32, + b: i32, + c: A, + d: i8, +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _s: S = Default::default(); + 0 +} diff --git a/src/test/ui/print_type_sizes/repr-align.stdout b/src/test/ui/print_type_sizes/repr-align.stdout new file mode 100644 index 000000000..33671bd8e --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs new file mode 100644 index 000000000..b8067c112 --- /dev/null +++ b/src/test/ui/print_type_sizes/repr_int_c.rs @@ -0,0 +1,25 @@ +// compile-flags: -Z print-type-sizes +// 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). + +#![feature(start)] +#![allow(dead_code)] + +#[repr(C, u8)] +enum ReprCu8 { + A(u16), + B, +} + +#[repr(u8)] +enum Repru8 { + A(u16), + B, +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 0 +} diff --git a/src/test/ui/print_type_sizes/repr_int_c.stdout b/src/test/ui/print_type_sizes/repr_int_c.stdout new file mode 100644 index 000000000..254b3c7a8 --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs new file mode 100644 index 000000000..06a62db4e --- /dev/null +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -0,0 +1,15 @@ +// 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. + +#![feature(never_type)] +#![feature(start)] + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _x: Option<!> = None; + let _y: Result<u32, !> = Ok(42); + let _z: Result<!, !> = loop {}; +} diff --git a/src/test/ui/print_type_sizes/uninhabited.stdout b/src/test/ui/print_type_sizes/uninhabited.stdout new file mode 100644 index 000000000..5eb5384bc --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs new file mode 100644 index 000000000..6c8553cc2 --- /dev/null +++ b/src/test/ui/print_type_sizes/variants.rs @@ -0,0 +1,26 @@ +// compile-flags: -Z print-type-sizes +// 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. + +#![feature(start)] + +pub struct SevenBytes([u8; 7]); +pub struct FiftyBytes([u8; 50]); + +pub enum Enum { + Small(SevenBytes), + Large(FiftyBytes), +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _e: Enum; + 0 +} diff --git a/src/test/ui/print_type_sizes/variants.stdout b/src/test/ui/print_type_sizes/variants.stdout new file mode 100644 index 000000000..641188154 --- /dev/null +++ b/src/test/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/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs new file mode 100644 index 000000000..e02a33109 --- /dev/null +++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs @@ -0,0 +1,47 @@ +// compile-flags: -Z print-type-sizes +// 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`. + +#![feature(start)] + +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, +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 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 {}, + }; + 0 +} diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.stdout b/src/test/ui/print_type_sizes/zero-sized-fields.stdout new file mode 100644 index 000000000..72f59c4bb --- /dev/null +++ b/src/test/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 |