Skip to content

Commit d4981e9

Browse files
authored
Rollup merge of rust-lang#46809 - eddyb:issue-46769-optimal, r=arielb1
rustc: do not raise the alignment of optimized enums to the niche's alignment. This is the improved fix for rust-lang#46769 that does not increase the size of any types (see also rust-lang#46808).
2 parents 9341321 + 5c3dcfa commit d4981e9

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

src/librustc/ty/layout.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -1484,27 +1484,25 @@ impl<'a, 'tcx> LayoutDetails {
14841484
Some(niche) => niche,
14851485
None => continue
14861486
};
1487+
let mut align = dl.aggregate_align;
14871488
let st = variants.iter().enumerate().map(|(j, v)| {
14881489
let mut st = univariant_uninterned(v,
14891490
&def.repr, StructKind::AlwaysSized)?;
14901491
st.variants = Variants::Single { index: j };
1492+
1493+
align = align.max(st.align);
1494+
14911495
Ok(st)
14921496
}).collect::<Result<Vec<_>, _>>()?;
14931497

14941498
let offset = st[i].fields.offset(field_index) + offset;
1495-
let LayoutDetails { mut size, mut align, .. } = st[i];
1499+
let size = st[i].size;
14961500

1497-
let mut niche_align = niche.value.align(dl);
14981501
let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {
14991502
Abi::Scalar(niche.clone())
15001503
} else {
1501-
if offset.abi_align(niche_align) != offset {
1502-
niche_align = dl.i8_align;
1503-
}
15041504
Abi::Aggregate { sized: true }
15051505
};
1506-
align = align.max(niche_align);
1507-
size = size.abi_align(align);
15081506

15091507
return Ok(tcx.intern_layout(LayoutDetails {
15101508
variants: Variants::NicheFilling {

src/test/run-pass/packed-struct-optimized-enum.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ impl<T: Copy> Clone for Packed<T> {
1919
fn sanity_check_size<T: Copy>(one: T) {
2020
let two = [one, one];
2121
let stride = (&two[1] as *const _ as usize) - (&two[0] as *const _ as usize);
22-
assert_eq!(stride, std::mem::size_of_val(&one));
22+
let (size, align) = (std::mem::size_of::<T>(), std::mem::align_of::<T>());
23+
assert_eq!(stride, size);
24+
assert_eq!(size % align, 0);
2325
}
2426

2527
fn main() {
@@ -32,5 +34,12 @@ fn main() {
3234
// In #46769, `Option<(Packed<&()>, bool)>` was found to have
3335
// pointer alignment, without actually being aligned in size.
3436
// E.g. on 64-bit platforms, it had alignment `8` but size `9`.
35-
sanity_check_size(Some((Packed(&()), true)));
37+
type PackedRefAndBool<'a> = (Packed<&'a ()>, bool);
38+
sanity_check_size::<Option<PackedRefAndBool>>(Some((Packed(&()), true)));
39+
40+
// Make sure we don't pay for the enum optimization in size,
41+
// e.g. we shouldn't need extra padding after the packed data.
42+
assert_eq!(std::mem::align_of::<Option<PackedRefAndBool>>(), 1);
43+
assert_eq!(std::mem::size_of::<Option<PackedRefAndBool>>(),
44+
std::mem::size_of::<PackedRefAndBool>());
3645
}

0 commit comments

Comments
 (0)