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:
commit
e7db42fb5b
|
@ -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 {
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue