diff options
| author | bors <bors@rust-lang.org> | 2017-12-18 20:44:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-12-18 20:44:18 +0000 |
| commit | e7db42fb5b9a620c5669711546663d0ccebf9291 (patch) | |
| tree | fe6313234b01b04761fc780066b27e6663eb6ea8 | |
| parent | b058dc0107b734b0a1a664ca0209366bb59eb3e9 (diff) | |
| parent | 087f1c23a70f889ea157c68b9db36c524e95ba8f (diff) | |
| download | rust-e7db42fb5b9a620c5669711546663d0ccebf9291.tar.gz rust-e7db42fb5b9a620c5669711546663d0ccebf9291.zip | |
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).
| -rw-r--r-- | src/librustc/ty/layout.rs | 3 | ||||
| -rw-r--r-- | src/test/run-pass/packed-struct-optimized-enum.rs | 13 |
2 files changed, 12 insertions, 4 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 42987e3dd78..a2692fb8f5a 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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 { diff --git a/src/test/run-pass/packed-struct-optimized-enum.rs b/src/test/run-pass/packed-struct-optimized-enum.rs index 876b74a042f..b8a1e6f2f54 100644 --- a/src/test/run-pass/packed-struct-optimized-enum.rs +++ b/src/test/run-pass/packed-struct-optimized-enum.rs @@ -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))); } |
