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..dc93bddbad8e2 --- /dev/null +++ b/src/test/ui/print_type_sizes/anonymous.rs @@ -0,0 +1,27 @@ +// 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 + +// 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 = 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 { } } +} 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..f7fdcac81daad --- /dev/null +++ b/src/test/ui/print_type_sizes/nullable.rs @@ -0,0 +1,69 @@ +// 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. +// +// 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(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: u8, val: NonZero, 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: NonZero, + post: u16, +} + +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..dd999c4a5e4c7 --- /dev/null +++ b/src/test/ui/print_type_sizes/nullable.stdout @@ -0,0 +1,27 @@ +print-type-size type: `IndirectNonZero`: 20 bytes, alignment: 4 bytes +print-type-size field `.pre`: 1 bytes +print-type-size padding: 3 bytes +print-type-size field `.nested`: 12 bytes, alignment: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size end padding: 2 bytes +print-type-size type: `MyOption>`: 20 bytes, alignment: 4 bytes +print-type-size variant `Some`: 20 bytes +print-type-size field `.0`: 20 bytes +print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes +print-type-size variant `Record`: 10 bytes +print-type-size field `.pre`: 1 bytes +print-type-size padding: 3 bytes +print-type-size field `.val`: 4 bytes, alignment: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size end padding: 2 bytes +print-type-size type: `NestedNonZero`: 12 bytes, alignment: 4 bytes +print-type-size field `.pre`: 1 bytes +print-type-size padding: 3 bytes +print-type-size field `.val`: 4 bytes, alignment: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size end padding: 2 bytes +print-type-size type: `MyOption>`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 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..cd7ef86d70ee3 --- /dev/null +++ b/src/test/ui/print_type_sizes/packed.rs @@ -0,0 +1,49 @@ +// 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. +// +// 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(untagged_unions)] + +#![allow(dead_code)] + +#[derive(Default)] +#[repr(packed)] +struct Packed { + 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, +} + +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..1278a7d7c92c6 --- /dev/null +++ b/src/test/ui/print_type_sizes/packed.stdout @@ -0,0 +1,17 @@ +print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size padding: 2 bytes +print-type-size field `.g`: 4 bytes, alignment: 4 bytes +print-type-size field `.c`: 1 bytes +print-type-size padding: 1 bytes +print-type-size field `.h`: 2 bytes, alignment: 2 bytes +print-type-size field `.d`: 1 bytes +print-type-size end padding: 3 bytes +print-type-size type: `Packed`: 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 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..af34a908ce883 --- /dev/null +++ b/src/test/ui/print_type_sizes/padding.rs @@ -0,0 +1,39 @@ +// 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. +// +// 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), +} + +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..bb95f790bd9e4 --- /dev/null +++ b/src/test/ui/print_type_sizes/padding.stdout @@ -0,0 +1,21 @@ +print-type-size type: `E1`: 12 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `A`: 5 bytes +print-type-size field `.0`: 4 bytes +print-type-size field `.1`: 1 bytes +print-type-size variant `B`: 8 bytes +print-type-size field `.0`: 8 bytes +print-type-size type: `E2`: 12 bytes, alignment: 4 bytes +print-type-size discriminant: 1 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 variant `B`: 11 bytes +print-type-size padding: 3 bytes +print-type-size field `.0`: 8 bytes, alignment: 4 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: 2 bytes +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