disable some layout optimizations for unsizable structs

This commit is contained in:
The 8472 2023-05-29 20:07:06 +02:00
parent 381b778d27
commit 3003d05a8b

View File

@ -57,48 +57,54 @@ fn univariant(
// run and bias niches to the right and then check which one is closer to one of the struct's // run and bias niches to the right and then check which one is closer to one of the struct's
// edges. // edges.
if let Some(layout) = &layout { if let Some(layout) = &layout {
if let Some(niche) = layout.largest_niche { // Don't try to calculate an end-biased layout for unsizable structs,
let head_space = niche.offset.bytes(); // otherwise we could end up with different layouts for
let niche_length = niche.value.size(dl).bytes(); // Foo<Type> and Foo<dyn Trait> which would break unsizing
let tail_space = layout.size.bytes() - head_space - niche_length; if !matches!(kind, StructKind::MaybeUnsized) {
if let Some(niche) = layout.largest_niche {
let head_space = niche.offset.bytes();
let niche_length = niche.value.size(dl).bytes();
let tail_space = layout.size.bytes() - head_space - niche_length;
// This may end up doing redundant work if the niche is already in the last field // This may end up doing redundant work if the niche is already in the last field
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get // (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
// the unpadded size so we try anyway. // the unpadded size so we try anyway.
if fields.len() > 1 && head_space != 0 && tail_space > 0 { if fields.len() > 1 && head_space != 0 && tail_space > 0 {
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End) let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
.expect("alt layout should always work"); .expect("alt layout should always work");
let niche = alt_layout let niche = alt_layout
.largest_niche .largest_niche
.expect("alt layout should have a niche like the regular one"); .expect("alt layout should have a niche like the regular one");
let alt_head_space = niche.offset.bytes(); let alt_head_space = niche.offset.bytes();
let alt_niche_len = niche.value.size(dl).bytes(); let alt_niche_len = niche.value.size(dl).bytes();
let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len; let alt_tail_space =
alt_layout.size.bytes() - alt_head_space - alt_niche_len;
debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());
let prefer_alt_layout = let prefer_alt_layout =
alt_head_space > head_space && alt_head_space > tail_space; alt_head_space > head_space && alt_head_space > tail_space;
debug!( debug!(
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
layout: {}\n\ layout: {}\n\
alt_layout: {}\n", alt_layout: {}\n",
layout.size.bytes(), layout.size.bytes(),
head_space, head_space,
niche_length, niche_length,
tail_space, tail_space,
alt_head_space, alt_head_space,
alt_niche_len, alt_niche_len,
alt_tail_space, alt_tail_space,
layout.fields.count(), layout.fields.count(),
prefer_alt_layout, prefer_alt_layout,
format_field_niches(&layout, &fields, &dl), format_field_niches(&layout, &fields, &dl),
format_field_niches(&alt_layout, &fields, &dl), format_field_niches(&alt_layout, &fields, &dl),
); );
if prefer_alt_layout { if prefer_alt_layout {
return Some(alt_layout); return Some(alt_layout);
}
} }
} }
} }