Skip to content

Commit 20528ba

Browse files
authoredNov 1, 2022
Rollup merge of #103729 - RalfJung:align-of-val-packed, r=oli-obk
interpret: fix align_of_val on packed types Fixes rust-lang/miri#2632 r? `@oli-obk`
2 parents 7dc3ace + d366471 commit 20528ba

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed
 

‎compiler/rustc_const_eval/src/interpret/eval_context.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
598598
// the last field). Can't have foreign types here, how would we
599599
// adjust alignment and size for them?
600600
let field = layout.field(self, layout.fields.count() - 1);
601-
let Some((unsized_size, unsized_align)) = self.size_and_align_of(metadata, &field)? else {
601+
let Some((unsized_size, mut unsized_align)) = self.size_and_align_of(metadata, &field)? else {
602602
// A field with an extern type. We don't know the actual dynamic size
603603
// or the alignment.
604604
return Ok(None);
@@ -614,6 +614,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
614614
// Return the sum of sizes and max of aligns.
615615
let size = sized_size + unsized_size; // `Size` addition
616616

617+
// Packed types ignore the alignment of their fields.
618+
if let ty::Adt(def, _) = layout.ty.kind() {
619+
if def.repr().packed() {
620+
unsized_align = sized_align;
621+
}
622+
}
623+
617624
// Choose max of two known alignments (combined value must
618625
// be aligned according to more restrictive of the two).
619626
let align = sized_align.max(unsized_align);

‎library/core/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![feature(bigint_helper_methods)]
66
#![feature(cell_update)]
77
#![feature(const_assume)]
8+
#![feature(const_align_of_val_raw)]
89
#![feature(const_black_box)]
910
#![feature(const_bool_to_option)]
1011
#![feature(const_caller_location)]
@@ -42,6 +43,7 @@
4243
#![feature(try_find)]
4344
#![feature(inline_const)]
4445
#![feature(is_sorted)]
46+
#![feature(layout_for_ptr)]
4547
#![feature(pattern)]
4648
#![feature(pin_macro)]
4749
#![feature(sort_internals)]

‎library/core/tests/mem.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::mem::*;
2+
use core::ptr;
23

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

79+
#[test]
80+
#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails
81+
fn align_of_val_raw_packed() {
82+
#[repr(C, packed)]
83+
struct B {
84+
f: [u32],
85+
}
86+
let storage = [0u8; 4];
87+
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
88+
assert_eq!(unsafe { align_of_val_raw(b) }, 1);
89+
90+
const ALIGN_OF_VAL_RAW: usize = {
91+
let storage = [0u8; 4];
92+
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
93+
unsafe { align_of_val_raw(b) }
94+
};
95+
assert_eq!(ALIGN_OF_VAL_RAW, 1);
96+
}
97+
7898
#[test]
7999
fn test_swap() {
80100
let mut x = 31337;

0 commit comments

Comments
 (0)
Please sign in to comment.