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 0000000000000..9ea08acd40bbd --- /dev/null +++ b/src/test/ui/print_type_sizes/anonymous.rs @@ -0,0 +1,25 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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. + +pub fn main() { + let _byte: u8 = Default::default(); + let _word: usize = Default::default(); + let _tuple: (u8, usize)= Default::default(); + 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 { } } +} 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 0000000000000..93bcd1c36e592 --- /dev/null +++ b/src/test/ui/print_type_sizes/generics.rs @@ -0,0 +1,73 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// 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. + +// 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 { + _car: T, + _cdr: T, +} + +impl Pair { + 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(x: T) { + let _v: Pair = Pair::new(x, x); + let _v2: Pair = + Pair::new(FiftyBytes::new(), FiftyBytes::new()); +} + +pub fn main() { + let _b: Pair = Pair::new(0, 0); + let _s: Pair = Pair::new(SevenBytes::new(), SevenBytes::new()); + let _z: ZeroSized = ZeroSized; + f1::(SevenBytes::new()); +} 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 0000000000000..0f02f39795365 --- /dev/null +++ b/src/test/ui/print_type_sizes/generics.stdout @@ -0,0 +1,14 @@ +print-type-size type: `Pair`: 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`: 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`: 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 0000000000000..2b5010767fdef --- /dev/null +++ b/src/test/ui/print_type_sizes/multiple_types.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// 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), +} + +pub fn main() { + let _e: Enum; + let _f: FiftyBytes; + let _s: SevenBytes; +} 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 0000000000000..eed9af26987b4 --- /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 `Small`: 7 bytes +print-type-size field `.0`: 7 bytes +print-type-size variant `Large`: 50 bytes +print-type-size field `.0`: 50 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/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs new file mode 100644 index 0000000000000..6008a346c059f --- /dev/null +++ b/src/test/ui/print_type_sizes/no_duplicates.rs @@ -0,0 +1,25 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// 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 main() { + let _s: SevenBytes = SevenBytes([0; 7]); +} 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 0000000000000..50180f356ea36 --- /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/nullable.rs b/src/test/ui/print_type_sizes/nullable.rs new file mode 100644 index 0000000000000..019ccef5bde26 --- /dev/null +++ b/src/test/ui/print_type_sizes/nullable.rs @@ -0,0 +1,65 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// This file illustrates how enums with a non-null field are handled, +// modelled after cases like `Option<&u32>` and such. +// +// It uses NonZero directly, rather than `&_` or `Unique<_>`, because +// the test is not set up to deal with target-dependent pointer width. + +#![feature(nonzero)] +#![allow(dead_code)] + +extern crate core; +use core::nonzero::{NonZero, Zeroable}; + +pub enum MyOption { None, Some(T) } + +impl Default for MyOption { + fn default() -> Self { MyOption::None } +} + +pub enum EmbeddedDiscr { + None, + Record { pre: u64, val: NonZero, post: u64 }, +} + +impl Default for EmbeddedDiscr { + fn default() -> Self { EmbeddedDiscr::None } +} + +#[derive(Default)] +pub struct IndirectNonZero { + pre: u64, + nested: NestedNonZero, + post: u64, +} + +pub struct NestedNonZero { + pre: u64, + val: NonZero, + post: u64, +} + +impl Default for NestedNonZero { + fn default() -> Self { + unsafe { + NestedNonZero { pre: 0, val: NonZero::new(Default::default()), post: 0 } + } + } +} + +pub fn main() { + let _x: MyOption> = Default::default(); + let _y: EmbeddedDiscr = Default::default(); + let _z: MyOption> = Default::default(); +} diff --git a/src/test/ui/print_type_sizes/nullable.stdout b/src/test/ui/print_type_sizes/nullable.stdout new file mode 100644 index 0000000000000..bdef845e2c368 --- /dev/null +++ b/src/test/ui/print_type_sizes/nullable.stdout @@ -0,0 +1,24 @@ +print-type-size type: `IndirectNonZero`: 40 bytes, alignment: 8 bytes +print-type-size field `.pre`: 8 bytes +print-type-size field `.nested`: 24 bytes +print-type-size field `.post`: 8 bytes +print-type-size type: `MyOption>`: 40 bytes, alignment: 8 bytes +print-type-size variant `Some`: 40 bytes +print-type-size field `.0`: 40 bytes +print-type-size type: `EmbeddedDiscr`: 24 bytes, alignment: 8 bytes +print-type-size variant `Record`: 24 bytes +print-type-size field `.pre`: 8 bytes +print-type-size field `.val`: 8 bytes +print-type-size field `.post`: 8 bytes +print-type-size type: `NestedNonZero`: 24 bytes, alignment: 8 bytes +print-type-size field `.pre`: 8 bytes +print-type-size field `.val`: 4 bytes +print-type-size padding bytes: 4 +print-type-size field `.post`: 8 bytes, alignment: 8 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 8 bytes +print-type-size variant `Some`: 8 bytes +print-type-size field `.0`: 8 bytes +print-type-size type: `core::nonzero::NonZero`: 8 bytes, alignment: 8 bytes +print-type-size field `.0`: 8 bytes +print-type-size type: `core::nonzero::NonZero`: 4 bytes, alignment: 4 bytes +print-type-size field `.0`: 4 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 0000000000000..546fc9ddc24f0 --- /dev/null +++ b/src/test/ui/print_type_sizes/packed.rs @@ -0,0 +1,45 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// This file illustrates how packing is handled; it should cause +// the elimination of padding that would normally be introduced +// to satisfy alignment desirata. + +#![feature(untagged_unions)] + +#![allow(dead_code)] + +#[derive(Default)] +#[repr(packed)] +struct Packed { + a: bool, + b: bool, + g: i32, + c: bool, + w: i64, + d: bool, +} + +#[derive(Default)] +struct Padded { + a: bool, + b: bool, + g: i32, + c: bool, + w: i64, + d: bool, +} + +pub fn main() { + let _c: Packed = Default::default(); + let _d: Padded = Default::default(); +} 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 0000000000000..a500871ed1a2f --- /dev/null +++ b/src/test/ui/print_type_sizes/packed.stdout @@ -0,0 +1,17 @@ +print-type-size type: `Padded`: 32 bytes, alignment: 8 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size padding bytes: 2 +print-type-size field `.g`: 4 bytes, alignment: 4 bytes +print-type-size field `.c`: 1 bytes +print-type-size padding bytes: 7 +print-type-size field `.w`: 8 bytes, alignment: 8 bytes +print-type-size field `.d`: 1 bytes +print-type-size end padding bytes: 7 +print-type-size type: `Packed`: 16 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 `.w`: 8 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 0000000000000..2e3601f927a2d --- /dev/null +++ b/src/test/ui/print_type_sizes/padding.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// 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. + +#![allow(dead_code)] + +struct S { + a: bool, + b: bool, + g: i32, +} + +enum E1 { + A(i64, i32), + B(S), +} + +enum E2 { + A(i32, i64), + B(S), +} + +fn main() { } 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 0000000000000..bb39c129f1333 --- /dev/null +++ b/src/test/ui/print_type_sizes/padding.stdout @@ -0,0 +1,21 @@ +print-type-size type: `E1`: 24 bytes, alignment: 8 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `A`: 16 bytes +print-type-size padding bytes: 4 +print-type-size field `.0`: 8 bytes, alignment: 8 bytes +print-type-size field `.1`: 4 bytes +print-type-size variant `B`: 8 bytes +print-type-size field `.0`: 8 bytes +print-type-size end padding bytes: 4 +print-type-size type: `E2`: 16 bytes, alignment: 8 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `A`: 12 bytes +print-type-size field `.0`: 4 bytes +print-type-size field `.1`: 8 bytes +print-type-size variant `B`: 8 bytes +print-type-size field `.0`: 8 bytes +print-type-size type: `S`: 8 bytes, alignment: 4 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size padding bytes: 2 +print-type-size field `.g`: 4 bytes, alignment: 4 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 0000000000000..875edb4515a17 --- /dev/null +++ b/src/test/ui/print_type_sizes/variants.rs @@ -0,0 +1,31 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes + +// 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), +} + +pub fn main() { + let _e: Enum; +} 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 0000000000000..eed9af26987b4 --- /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 `Small`: 7 bytes +print-type-size field `.0`: 7 bytes +print-type-size variant `Large`: 50 bytes +print-type-size field `.0`: 50 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