about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-12-18 15:17:29 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-12-20 03:45:40 +0200
commit5c3dcfaf8570abca15c006920fd2b4b150ecaad7 (patch)
treef36c5af6b8985137bcd9a7c585fdc779e62dfaec /src
parentb39c4bc12358078f77ddd01288b24252f757f37d (diff)
rustc: do not raise the alignment of optimized enums to the niche's alignment.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/layout.rs12
-rw-r--r--src/test/run-pass/packed-struct-optimized-enum.rs13
2 files changed, 16 insertions, 9 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index a2692fb8f5a..978c6c74233 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::<Result<Vec<_>, _>>()?;
 
                             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 b8a1e6f2f54..7968ae2278a 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<T: Copy> Clone for Packed<T> {
 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));
+    let (size, align) = (std::mem::size_of::<T>(), std::mem::align_of::<T>());
+    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::<Option<PackedRefAndBool>>(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::<Option<PackedRefAndBool>>(), 1);
+    assert_eq!(std::mem::size_of::<Option<PackedRefAndBool>>(),
+               std::mem::size_of::<PackedRefAndBool>());
 }