where
L: HasLocalDecls<'tcx>,
{
- for (place_base, elem) in place.iter_projections().rev() {
- match elem {
- // encountered a Deref, which is ABI-aligned
- ProjectionElem::Deref => break,
- ProjectionElem::Field(..) => {
- let ty = place_base.ty(local_decls, tcx).ty;
- match ty.kind() {
- ty::Adt(def, _) => return def.repr().pack,
- _ => {}
- }
- }
- _ => {}
- }
- }
-
- None
+ place
+ .iter_projections()
+ .rev()
+ // Stop at `Deref`; standard ABI alignment applies there.
+ .take_while(|(_base, elem)| !matches!(elem, ProjectionElem::Deref))
+ // Consider the packed alignments at play here...
+ .filter_map(|(base, _elem)| {
+ base.ty(local_decls, tcx).ty.ty_adt_def().and_then(|adt| adt.repr().pack)
+ })
+ // ... and compute their minimum.
+ // The overall smallest alignment is what matters.
+ .min()
}
let _ = &packed2.y; // ok, has align 2 in packed(2) struct
let _ = &packed2.z; // ok, has align 1
}
+
+ unsafe {
+ struct U16(u16);
+
+ impl Drop for U16 {
+ fn drop(&mut self) {
+ println!("{:p}", self);
+ }
+ }
+
+ struct HasDrop;
+
+ impl Drop for HasDrop {
+ fn drop(&mut self) {}
+ }
+
+ #[allow(unused)]
+ struct Wrapper {
+ a: U16,
+ b: HasDrop,
+ }
+ #[allow(unused)]
+ #[repr(packed(2))]
+ struct Wrapper2 {
+ a: U16,
+ b: HasDrop,
+ }
+
+ // An outer struct with more restrictive packing than the inner struct -- make sure we
+ // notice that!
+ #[repr(packed)]
+ struct Misalign<T>(u8, T);
+
+ let m1 = Misalign(
+ 0,
+ Wrapper {
+ a: U16(10),
+ b: HasDrop,
+ },
+ );
+ let _ref = &m1.1.a; //~ ERROR reference to packed field
+ //~^ previously accepted
+
+ let m2 = Misalign(
+ 0,
+ Wrapper2 {
+ a: U16(10),
+ b: HasDrop,
+ },
+ );
+ let _ref = &m2.1.a; //~ ERROR reference to packed field
+ //~^ previously accepted
+ }
}
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: aborting due to 7 previous errors
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:90:20
+ |
+LL | let _ref = &m1.1.a;
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:100:20
+ |
+LL | let _ref = &m2.1.a;
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+error: aborting due to 9 previous errors
Future incompatibility report: Future breakage diagnostic:
error: reference to packed field is unaligned
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:90:20
+ |
+LL | let _ref = &m1.1.a;
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:100:20
+ |
+LL | let _ref = &m2.1.a;
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+