You can use the compiler flag --print-type-sizes (requires nightly). If using Cargo, use cargo rustc (note it requires cargo clean, thanks @tifrel):
cargo +nightly rustc -- -Zprint-type-sizes
E.g.:
struct Foo(i16, i32);
fn main() { _ = Foo(0, 0); }
Output (rustc +nightly -Zprint-type-sizes file.rs):
print-type-size type: `Foo`: 8 bytes, alignment: 4 bytes
print-type-size field `.1`: 4 bytes
print-type-size field `.0`: 2 bytes
print-type-size end padding: 2 bytes
print-type-size type: `[closure@std::rt::lang_start<()>::{closure#0}]`: 8 bytes, alignment: 8 bytes
print-type-size end padding: 8 bytes
print-type-size type: `std::result::Result<isize, !>`: 8 bytes, alignment: 8 bytes
print-type-size variant `Ok`: 8 bytes
print-type-size field `.0`: 8 bytes
print-type-size type: `std::process::ExitCode`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `std::sys::windows::process::ExitCode`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
There are some hidden types from main(), and our type. We can see it is 8 bytes, with 4 bytes alignment (because of the i32). We can also see the compiler reordered the fields so that the i16 comes last, and then 2 padding bytes. Note that it prints only used types (this is why we used it in main()), and prints monomorphized types (after generics are applied).
Another way to print more verbose and more specific type information, is to use the perm-unstable rustc_layout attribute:
#![feature(rustc_attrs)]
#[rustc_layout(debug)]
struct Foo(i16, i32);
fn main() {}
error: layout_of(Foo) = Layout {
fields: Arbitrary {
offsets: [
Size {
raw: 4,
},
Size {
raw: 0,
},
],
memory_index: [
1,
0,
],
},
variants: Single {
index: 0,
},
abi: ScalarPair(
Scalar {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
Scalar {
value: Int(
I16,
true,
),
valid_range: 0..=65535,
},
),
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: Align {
pow2: 3,
},
},
size: Size {
raw: 8,
},
}
--> rs.rs:3:1
|
3 | struct Foo(i16, i32);
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
Note however this prints the unmonomorphized types, so struct Foo<T>(T) will print layout error: Unknown(T). Because of that, it also doesn't require the type to be used.