Skip to content

Commit

Permalink
Tests of -Z print-type-sizes functionality.
Browse files Browse the repository at this point in the history
Note that the tests have been updated to initialize the local
variables; originally it was enough just to declare them.

Back when I started this, the `layout_cache` contained entries even
just for types that had been declared but not initialized. Apparently
things have changed in the interim so that if I want one of those
layouts to be computed, I need to actually initialize the value.

(Incidentally, this shows a weakness in the strategy of just walking
the `layout_cache`; the original strategy of using a MIR visitor would
probably have exhibited more robustness in terms of consistent output,
but it had other weaknesses so I chose not to reimplement it. At
least, not yet.)
  • Loading branch information
pnkfelix committed Nov 21, 2016
1 parent cf2d375 commit 559c135
Show file tree
Hide file tree
Showing 15 changed files with 425 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/test/ui/print_type_sizes/anonymous.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 { } }
}
73 changes: 73 additions & 0 deletions src/test/ui/print_type_sizes/generics.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<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 main() {
let _b: Pair<u8> = Pair::new(0, 0);
let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
let _z: ZeroSized = ZeroSized;
f1::<SevenBytes>(SevenBytes::new());
}
14 changes: 14 additions & 0 deletions src/test/ui/print_type_sizes/generics.stdout
Original file line number Diff line number Diff line change
@@ -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
28 changes: 28 additions & 0 deletions src/test/ui/print_type_sizes/multiple_types.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
}
10 changes: 10 additions & 0 deletions src/test/ui/print_type_sizes/multiple_types.stdout
Original file line number Diff line number Diff line change
@@ -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
25 changes: 25 additions & 0 deletions src/test/ui/print_type_sizes/no_duplicates.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]);
}
2 changes: 2 additions & 0 deletions src/test/ui/print_type_sizes/no_duplicates.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
print-type-size field `.0`: 7 bytes
65 changes: 65 additions & 0 deletions src/test/ui/print_type_sizes/nullable.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> { None, Some(T) }

impl<T> Default for MyOption<T> {
fn default() -> Self { MyOption::None }
}

pub enum EmbeddedDiscr {
None,
Record { pre: u64, val: NonZero<u64>, post: u64 },
}

impl Default for EmbeddedDiscr {
fn default() -> Self { EmbeddedDiscr::None }
}

#[derive(Default)]
pub struct IndirectNonZero<T: Zeroable> {
pre: u64,
nested: NestedNonZero<T>,
post: u64,
}

pub struct NestedNonZero<T: Zeroable> {
pre: u64,
val: NonZero<T>,
post: u64,
}

impl<T: Zeroable+Default> Default for NestedNonZero<T> {
fn default() -> Self {
unsafe {
NestedNonZero { pre: 0, val: NonZero::new(Default::default()), post: 0 }
}
}
}

pub fn main() {
let _x: MyOption<NonZero<u64>> = Default::default();
let _y: EmbeddedDiscr = Default::default();
let _z: MyOption<IndirectNonZero<u32>> = Default::default();
}
24 changes: 24 additions & 0 deletions src/test/ui/print_type_sizes/nullable.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
print-type-size type: `IndirectNonZero<u32>`: 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<IndirectNonZero<u32>>`: 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<u32>`: 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<core::nonzero::NonZero<u64>>`: 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<u64>`: 8 bytes, alignment: 8 bytes
print-type-size field `.0`: 8 bytes
print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
45 changes: 45 additions & 0 deletions src/test/ui/print_type_sizes/packed.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
}
17 changes: 17 additions & 0 deletions src/test/ui/print_type_sizes/packed.stdout
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions src/test/ui/print_type_sizes/padding.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }
21 changes: 21 additions & 0 deletions src/test/ui/print_type_sizes/padding.stdout
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 559c135

Please sign in to comment.