Auto merge of #46808 - eddyb:issue-46769-quick, r=arielb1

rustc: ensure optimized enums have a properly aligned size.

Fixes #46769 by padding the optimized enums wrapping packed data as necessary.

Note that this is not the only way to solve this - on nightly, #46436 makes it easier to fix without adding new padding because of the replacement of `packed` flags with a non-redundant scheme.
But because it can't be backported, the optimal fix will be in a separate nightly-only PR (#46809).
This commit is contained in:
bors 2017-12-18 20:44:18 +00:00
commit e7db42fb5b
2 changed files with 12 additions and 4 deletions

View File

@ -1492,7 +1492,7 @@ impl<'a, 'tcx> LayoutDetails {
}).collect::<Result<Vec<_>, _>>()?;
let offset = st[i].fields.offset(field_index) + offset;
let LayoutDetails { size, mut align, .. } = st[i];
let LayoutDetails { mut size, mut align, .. } = st[i];
let mut niche_align = niche.value.align(dl);
let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {
@ -1504,6 +1504,7 @@ impl<'a, 'tcx> LayoutDetails {
Abi::Aggregate { sized: true }
};
align = align.max(niche_align);
size = size.abi_align(align);
return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::NicheFilling {

View File

@ -16,14 +16,21 @@ impl<T: Copy> Clone for Packed<T> {
fn clone(&self) -> Self { *self }
}
fn main() {
let one = (Some(Packed((&(), 0))), true);
fn sanity_check_size<T: Copy>(one: T) {
let two = [one, one];
let stride = (&two[1] as *const _ as usize) - (&two[0] as *const _ as usize);
assert_eq!(stride, std::mem::size_of_val(&one));
}
fn main() {
// This can fail if rustc and LLVM disagree on the size of a type.
// In this case, `Option<Packed<(&(), u32)>>` was erronously not
// marked as packed despite needing alignment `1` and containing
// its `&()` discriminant, which has alignment larger than `1`.
assert_eq!(stride, std::mem::size_of_val(&one));
sanity_check_size((Some(Packed((&(), 0))), true));
// In #46769, `Option<(Packed<&()>, bool)>` was found to have
// pointer alignment, without actually being aligned in size.
// E.g. on 64-bit platforms, it had alignment `8` but size `9`.
sanity_check_size(Some((Packed(&()), true)));
}