From 5c3dcfaf8570abca15c006920fd2b4b150ecaad7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 18 Dec 2017 15:17:29 +0200 Subject: [PATCH] rustc: do not raise the alignment of optimized enums to the niche's alignment. --- src/librustc/ty/layout.rs | 12 +++++------- src/test/run-pass/packed-struct-optimized-enum.rs | 13 +++++++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a2692fb8f5a1e..978c6c742339c 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1484,27 +1484,25 @@ impl<'a, 'tcx> LayoutDetails { Some(niche) => niche, None => continue }; + let mut align = dl.aggregate_align; let st = variants.iter().enumerate().map(|(j, v)| { let mut st = univariant_uninterned(v, &def.repr, StructKind::AlwaysSized)?; st.variants = Variants::Single { index: j }; + + align = align.max(st.align); + Ok(st) }).collect::, _>>()?; let offset = st[i].fields.offset(field_index) + offset; - let LayoutDetails { mut size, mut align, .. } = st[i]; + let size = st[i].size; - let mut niche_align = niche.value.align(dl); let abi = if offset.bytes() == 0 && niche.value.size(dl) == size { Abi::Scalar(niche.clone()) } else { - if offset.abi_align(niche_align) != offset { - niche_align = dl.i8_align; - } Abi::Aggregate { sized: true } }; - align = align.max(niche_align); - size = size.abi_align(align); return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::NicheFilling { diff --git a/src/test/run-pass/packed-struct-optimized-enum.rs b/src/test/run-pass/packed-struct-optimized-enum.rs index b8a1e6f2f5400..7968ae2278ae9 100644 --- a/src/test/run-pass/packed-struct-optimized-enum.rs +++ b/src/test/run-pass/packed-struct-optimized-enum.rs @@ -19,7 +19,9 @@ impl Clone for Packed { fn sanity_check_size(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)); + let (size, align) = (std::mem::size_of::(), std::mem::align_of::()); + assert_eq!(stride, size); + assert_eq!(size % align, 0); } fn main() { @@ -32,5 +34,12 @@ fn main() { // 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))); + type PackedRefAndBool<'a> = (Packed<&'a ()>, bool); + sanity_check_size::>(Some((Packed(&()), true))); + + // Make sure we don't pay for the enum optimization in size, + // e.g. we shouldn't need extra padding after the packed data. + assert_eq!(std::mem::align_of::>(), 1); + assert_eq!(std::mem::size_of::>(), + std::mem::size_of::()); }