1
Fork 0

allow reordering of the last field of a MaybeUnsized struct if it's a ZST

This commit is contained in:
Erik Desjardins 2020-08-16 19:25:24 -04:00
parent d3b9ece4c0
commit e5d85f917b

View file

@ -289,25 +289,32 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let optimize = !repr.inhibit_struct_field_reordering_opt(); let optimize = !repr.inhibit_struct_field_reordering_opt();
if optimize { if optimize {
let end =
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index[..end];
let field_align = |f: &TyAndLayout<'_>| { let field_align = |f: &TyAndLayout<'_>| {
if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
}; };
match kind { match kind {
StructKind::AlwaysSized | StructKind::MaybeUnsized => { StructKind::AlwaysSized => {
optimizing.sort_by_key(|&x| { inverse_memory_index.sort_by_key(|&x| {
// Place ZSTs first to avoid "interesting offsets", // Place ZSTs first to avoid "interesting offsets",
// especially with only one or two non-ZST fields. // especially with only one or two non-ZST fields.
let f = &fields[x as usize]; let f = &fields[x as usize];
(!f.is_zst(), cmp::Reverse(field_align(f))) (!f.is_zst(), cmp::Reverse(field_align(f)))
}); });
} }
StructKind::MaybeUnsized => {
// Sort in descending alignment, except for the last field,
// which may be accessed through an unsized type.
inverse_memory_index[..fields.len() - 1]
.sort_by_key(|&x| cmp::Reverse(field_align(&fields[x as usize])));
// Place ZSTs first to avoid "interesting offsets".
// This will reorder the last field if it is a ZST, which is okay because
// there's nothing in memory that could be accessed through an unsized type.
inverse_memory_index.sort_by_key(|&x| !fields[x as usize].is_zst());
}
StructKind::Prefixed(..) => { StructKind::Prefixed(..) => {
// Sort in ascending alignment so that the layout stay optimal // Sort in ascending alignment so that the layout stay optimal
// regardless of the prefix // regardless of the prefix
optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); inverse_memory_index.sort_by_key(|&x| field_align(&fields[x as usize]));
} }
} }
} }