Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix -Z print-type-sizes's handling of zero-sized fields. #67215

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/librustc_session/code_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,12 @@ impl CodeStats {

let mut min_offset = discr_size;

// We want to print fields by increasing offset.
// We want to print fields by increasing offset. We also want
// zero-sized fields before non-zero-sized fields, otherwise
// the loop below goes wrong; hence the `f.size` in the sort
// key.
let mut fields = fields.clone();
fields.sort_by_key(|f| f.offset);
fields.sort_by_key(|f| (f.offset, f.size));

for field in fields.iter() {
let FieldInfo { ref name, offset, size, align } = *field;
Expand All @@ -146,7 +149,7 @@ impl CodeStats {
}

if offset < min_offset {
// if this happens something is very wrong
// If this happens it's probably a union.
println!("print-type-size {}field `.{}`: {} bytes, \
offset: {} bytes, \
alignment: {} bytes",
Expand Down
46 changes: 46 additions & 0 deletions src/test/ui/print_type_sizes/zero-sized-fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// compile-flags: -Z print-type-sizes
// build-pass (FIXME(62277): could be check-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
}
16 changes: 16 additions & 0 deletions src/test/ui/print_type_sizes/zero-sized-fields.stdout
Original file line number Diff line number Diff line change
@@ -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