Skip to content

Commit 3003d05

Browse files
committed
disable some layout optimizations for unsizable structs
1 parent 381b778 commit 3003d05

File tree

1 file changed

+48
-42
lines changed

1 file changed

+48
-42
lines changed

compiler/rustc_abi/src/layout.rs

+48-42
Original file line numberDiff line numberDiff line change
@@ -57,48 +57,54 @@ pub trait LayoutCalculator {
5757
// run and bias niches to the right and then check which one is closer to one of the struct's
5858
// edges.
5959
if let Some(layout) = &layout {
60-
if let Some(niche) = layout.largest_niche {
61-
let head_space = niche.offset.bytes();
62-
let niche_length = niche.value.size(dl).bytes();
63-
let tail_space = layout.size.bytes() - head_space - niche_length;
64-
65-
// This may end up doing redundant work if the niche is already in the last field
66-
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
67-
// the unpadded size so we try anyway.
68-
if fields.len() > 1 && head_space != 0 && tail_space > 0 {
69-
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
70-
.expect("alt layout should always work");
71-
let niche = alt_layout
72-
.largest_niche
73-
.expect("alt layout should have a niche like the regular one");
74-
let alt_head_space = niche.offset.bytes();
75-
let alt_niche_len = niche.value.size(dl).bytes();
76-
let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len;
77-
78-
debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());
79-
80-
let prefer_alt_layout =
81-
alt_head_space > head_space && alt_head_space > tail_space;
82-
83-
debug!(
84-
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
85-
layout: {}\n\
86-
alt_layout: {}\n",
87-
layout.size.bytes(),
88-
head_space,
89-
niche_length,
90-
tail_space,
91-
alt_head_space,
92-
alt_niche_len,
93-
alt_tail_space,
94-
layout.fields.count(),
95-
prefer_alt_layout,
96-
format_field_niches(&layout, &fields, &dl),
97-
format_field_niches(&alt_layout, &fields, &dl),
98-
);
99-
100-
if prefer_alt_layout {
101-
return Some(alt_layout);
60+
// Don't try to calculate an end-biased layout for unsizable structs,
61+
// otherwise we could end up with different layouts for
62+
// Foo<Type> and Foo<dyn Trait> which would break unsizing
63+
if !matches!(kind, StructKind::MaybeUnsized) {
64+
if let Some(niche) = layout.largest_niche {
65+
let head_space = niche.offset.bytes();
66+
let niche_length = niche.value.size(dl).bytes();
67+
let tail_space = layout.size.bytes() - head_space - niche_length;
68+
69+
// This may end up doing redundant work if the niche is already in the last field
70+
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
71+
// the unpadded size so we try anyway.
72+
if fields.len() > 1 && head_space != 0 && tail_space > 0 {
73+
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
74+
.expect("alt layout should always work");
75+
let niche = alt_layout
76+
.largest_niche
77+
.expect("alt layout should have a niche like the regular one");
78+
let alt_head_space = niche.offset.bytes();
79+
let alt_niche_len = niche.value.size(dl).bytes();
80+
let alt_tail_space =
81+
alt_layout.size.bytes() - alt_head_space - alt_niche_len;
82+
83+
debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());
84+
85+
let prefer_alt_layout =
86+
alt_head_space > head_space && alt_head_space > tail_space;
87+
88+
debug!(
89+
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
90+
layout: {}\n\
91+
alt_layout: {}\n",
92+
layout.size.bytes(),
93+
head_space,
94+
niche_length,
95+
tail_space,
96+
alt_head_space,
97+
alt_niche_len,
98+
alt_tail_space,
99+
layout.fields.count(),
100+
prefer_alt_layout,
101+
format_field_niches(&layout, &fields, &dl),
102+
format_field_niches(&alt_layout, &fields, &dl),
103+
);
104+
105+
if prefer_alt_layout {
106+
return Some(alt_layout);
107+
}
102108
}
103109
}
104110
}

0 commit comments

Comments
 (0)