| 1 | #![warn (rust_2018_idioms, single_use_lifetimes)] |
| 2 | // unaligned_references did not exist in older compilers and safe_packed_borrows was removed in the latest compilers. |
| 3 | // https://github.com/rust-lang/rust/pull/82525 |
| 4 | #![allow (unknown_lints, renamed_and_removed_lints)] |
| 5 | #![forbid (unaligned_references, safe_packed_borrows)] |
| 6 | |
| 7 | use std::cell::Cell; |
| 8 | |
| 9 | // Ensure that the compiler doesn't copy the fields |
| 10 | // of #[repr(packed)] types during drop, if the field has alignment 1 |
| 11 | // (that is, any reference to the field is guaranteed to have proper alignment) |
| 12 | // We are currently unable to statically prevent the usage of #[pin_project] |
| 13 | // on #[repr(packed)] types composed entirely of fields of alignment 1. |
| 14 | // This shouldn't lead to undefined behavior, as long as the compiler doesn't |
| 15 | // try to move the field anyway during drop. |
| 16 | // |
| 17 | // This tests validates that the compiler is doing what we expect. |
| 18 | #[test] |
| 19 | fn weird_repr_packed() { |
| 20 | // We keep track of the field address during |
| 21 | // drop using a thread local, to avoid changing |
| 22 | // the layout of our #[repr(packed)] type. |
| 23 | thread_local! { |
| 24 | static FIELD_ADDR: Cell<usize> = Cell::new(0); |
| 25 | } |
| 26 | |
| 27 | #[repr (packed)] |
| 28 | struct Struct { |
| 29 | field: u8, |
| 30 | } |
| 31 | |
| 32 | impl Drop for Struct { |
| 33 | fn drop(&mut self) { |
| 34 | FIELD_ADDR.with(|f| { |
| 35 | f.set(&self.field as *const u8 as usize); |
| 36 | }); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | #[allow (clippy::let_and_return)] |
| 41 | let field_addr = { |
| 42 | // We let this field drop by going out of scope, |
| 43 | // rather than explicitly calling drop(foo). |
| 44 | // Calling drop(foo) causes 'foo' to be moved |
| 45 | // into the 'drop' function, resulting in a different |
| 46 | // address. |
| 47 | let x = Struct { field: 27 }; |
| 48 | let field_addr = &x.field as *const u8 as usize; |
| 49 | field_addr |
| 50 | }; |
| 51 | assert_eq!(field_addr, FIELD_ADDR.with(Cell::get)); |
| 52 | } |
| 53 | |