Skip to content

Commit

Permalink
Rollup merge of #103729 - RalfJung:align-of-val-packed, r=oli-obk
Browse files Browse the repository at this point in the history
interpret: fix align_of_val on packed types

Fixes rust-lang/miri#2632

r? `@oli-obk`
  • Loading branch information
Dylan-DPC authored Nov 1, 2022
2 parents 7dc3ace + d366471 commit 20528ba
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
9 changes: 8 additions & 1 deletion compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// the last field). Can't have foreign types here, how would we
// adjust alignment and size for them?
let field = layout.field(self, layout.fields.count() - 1);
let Some((unsized_size, unsized_align)) = self.size_and_align_of(metadata, &field)? else {
let Some((unsized_size, mut unsized_align)) = self.size_and_align_of(metadata, &field)? else {
// A field with an extern type. We don't know the actual dynamic size
// or the alignment.
return Ok(None);
Expand All @@ -614,6 +614,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Return the sum of sizes and max of aligns.
let size = sized_size + unsized_size; // `Size` addition

// Packed types ignore the alignment of their fields.
if let ty::Adt(def, _) = layout.ty.kind() {
if def.repr().packed() {
unsized_align = sized_align;
}
}

// Choose max of two known alignments (combined value must
// be aligned according to more restrictive of the two).
let align = sized_align.max(unsized_align);
Expand Down
2 changes: 2 additions & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(const_assume)]
#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]
#![feature(const_bool_to_option)]
#![feature(const_caller_location)]
Expand Down Expand Up @@ -42,6 +43,7 @@
#![feature(try_find)]
#![feature(inline_const)]
#![feature(is_sorted)]
#![feature(layout_for_ptr)]
#![feature(pattern)]
#![feature(pin_macro)]
#![feature(sort_internals)]
Expand Down
20 changes: 20 additions & 0 deletions library/core/tests/mem.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::mem::*;
use core::ptr;

#[cfg(panic = "unwind")]
use std::rc::Rc;
Expand Down Expand Up @@ -75,6 +76,25 @@ fn align_of_val_basic() {
assert_eq!(align_of_val(&1u32), 4);
}

#[test]
#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails
fn align_of_val_raw_packed() {
#[repr(C, packed)]
struct B {
f: [u32],
}
let storage = [0u8; 4];
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
assert_eq!(unsafe { align_of_val_raw(b) }, 1);

const ALIGN_OF_VAL_RAW: usize = {
let storage = [0u8; 4];
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
unsafe { align_of_val_raw(b) }
};
assert_eq!(ALIGN_OF_VAL_RAW, 1);
}

#[test]
fn test_swap() {
let mut x = 31337;
Expand Down

0 comments on commit 20528ba

Please sign in to comment.