about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-14 07:19:07 +0000
committerbors <bors@rust-lang.org>2023-12-14 07:19:07 +0000
commit1a8afa0e748008708950e1a9ff62c598e2cfb3ea (patch)
tree7ceeff47da477f9eca5cb3be5e318143ea21a83c /src
parentd23e1a689426638a5146c204e09278433c509610 (diff)
parent7e4c4271f44055b4dbd6f09aad19624254d67f22 (diff)
downloadrust-1a8afa0e748008708950e1a9ff62c598e2cfb3ea.tar.gz
rust-1a8afa0e748008708950e1a9ff62c598e2cfb3ea.zip
Auto merge of #118538 - RalfJung:size-of-val-comments, r=WaffleLapkin
fix dynamic size/align computation logic for packed types with dyn trait tail

This logic was never updated to support `packed(N)` where `N > 1`, and it turns out to be wrong for that case.

Fixes https://github.com/rust-lang/rust/issues/80925

`@bjorn3` I have not looked at cranelift; I assume it basically copied the size-of-val logic and hence could use much the same patch.
Diffstat (limited to 'src')
-rw-r--r--src/tools/miri/tests/pass/packed-struct-dyn-trait.rs21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs b/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs
new file mode 100644
index 00000000000..bb73c26c18a
--- /dev/null
+++ b/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs
@@ -0,0 +1,21 @@
+// run-pass
+use std::ptr::addr_of;
+
+// When the unsized tail is a `dyn Trait`, its alignments is only dynamically known. This means the
+// packed(2) needs to be applied at runtime: the actual alignment of the field is `min(2,
+// usual_alignment)`. Here we check that we do this right by comparing size, alignment, and field
+// offset before and after unsizing.
+fn main() {
+    #[repr(C, packed(2))]
+    struct Packed<T: ?Sized>(u8, core::mem::ManuallyDrop<T>);
+
+    let p = Packed(0, core::mem::ManuallyDrop::new(1));
+    let p: &Packed<usize> = &p;
+    let sized = (core::mem::size_of_val(p), core::mem::align_of_val(p));
+    let sized_offset = unsafe { addr_of!(p.1).cast::<u8>().offset_from(addr_of!(p.0)) };
+    let p: &Packed<dyn Send> = p;
+    let un_sized = (core::mem::size_of_val(p), core::mem::align_of_val(p));
+    let un_sized_offset = unsafe { addr_of!(p.1).cast::<u8>().offset_from(addr_of!(p.0)) };
+    assert_eq!(sized, un_sized);
+    assert_eq!(sized_offset, un_sized_offset);
+}