diff --git a/src/lib.rs b/src/lib.rs index c29cd0c..c52134f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -301,10 +301,8 @@ macro_rules! __pin_project_internal { // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. // - // Taking a reference to a packed field is unsafe, amd appplying - // #[forbid(safe_packed_borrows)] makes sure that doing this without - // an 'unsafe' block (which we deliberately do not generate) - // is a hard error. + // Taking a reference to a packed field is UB, and applying + // `#[forbid(unaligned_references)]` makes sure that doing this is a hard error. // // If the struct ends up having #[repr(packed)] applied somehow, // this will generate an (unfriendly) error message. Under all reasonable @@ -312,7 +310,16 @@ macro_rules! __pin_project_internal { // a much nicer error above. // // See https://github.com/taiki-e/pin-project/pull/34 for more details. - #[forbid(safe_packed_borrows)] + // + // Note: + // - Lint-based tricks aren't perfect, but they're much better than nothing: + // https://github.com/taiki-e/pin-project-lite/issues/26 + // + // - Enable both unaligned_references and safe_packed_borrows lints + // because unaligned_references lint does not exist in older compilers: + // https://github.com/taiki-e/pin-project-lite/pull/55 + // https://github.com/rust-lang/rust/pull/82525 + #[forbid(unaligned_references, safe_packed_borrows)] fn __assert_not_repr_packed <$($impl_generics)*> (this: &$ident <$($ty_generics)*>) $(where $($where_clause)*)? diff --git a/tests/expand/tests/expand/default-struct.expanded.rs b/tests/expand/tests/expand/default-struct.expanded.rs index 88e5a27..01f0959 100644 --- a/tests/expand/tests/expand/default-struct.expanded.rs +++ b/tests/expand/tests/expand/default-struct.expanded.rs @@ -64,7 +64,7 @@ const _: () = { #[allow(clippy::drop_bounds, drop_bounds)] impl MustNotImplDrop for T {} impl MustNotImplDrop for Struct {} - #[forbid(safe_packed_borrows)] + #[forbid(unaligned_references, safe_packed_borrows)] fn __assert_not_repr_packed(this: &Struct) { let _ = &this.pinned; let _ = &this.unpinned; diff --git a/tests/expand/tests/expand/pub-struct.expanded.rs b/tests/expand/tests/expand/pub-struct.expanded.rs index 87ff5c3..2ebfc4f 100644 --- a/tests/expand/tests/expand/pub-struct.expanded.rs +++ b/tests/expand/tests/expand/pub-struct.expanded.rs @@ -64,7 +64,7 @@ const _: () = { #[allow(clippy::drop_bounds, drop_bounds)] impl MustNotImplDrop for T {} impl MustNotImplDrop for Struct {} - #[forbid(safe_packed_borrows)] + #[forbid(unaligned_references, safe_packed_borrows)] fn __assert_not_repr_packed(this: &Struct) { let _ = &this.pinned; let _ = &this.unpinned; diff --git a/tests/ui/packed.rs b/tests/ui/packed.rs index 0bccc1f..507a038 100644 --- a/tests/ui/packed.rs +++ b/tests/ui/packed.rs @@ -1,16 +1,16 @@ use pin_project_lite::pin_project; -pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +pin_project! { //~ ERROR reference to packed field is unaligned #[repr(packed, C)] - struct A { + struct Packed { #[pin] field: u16, } } -pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +pin_project! { //~ ERROR reference to packed field is unaligned #[repr(packed(2))] - struct C { + struct PackedN { #[pin] field: u32, } diff --git a/tests/ui/packed.stderr b/tests/ui/packed.stderr index a976163..14ffc86 100644 --- a/tests/ui/packed.stderr +++ b/tests/ui/packed.stderr @@ -1,9 +1,61 @@ +error: reference to packed field is unaligned + --> $DIR/packed.rs:3:1 + | +3 | / pin_project! { //~ ERROR reference to packed field is unaligned +4 | | #[repr(packed, C)] +5 | | struct Packed { +6 | | #[pin] +7 | | field: u16, +8 | | } +9 | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/packed.rs:3:1 + | +3 | / pin_project! { //~ ERROR reference to packed field is unaligned +4 | | #[repr(packed, C)] +5 | | struct Packed { +6 | | #[pin] +7 | | field: u16, +8 | | } +9 | | } + | |_^ + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: reference to packed field is unaligned + --> $DIR/packed.rs:11:1 + | +11 | / pin_project! { //~ ERROR reference to packed field is unaligned +12 | | #[repr(packed(2))] +13 | | struct PackedN { +14 | | #[pin] +15 | | field: u32, +16 | | } +17 | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/packed.rs:11:1 + | +11 | / pin_project! { //~ ERROR reference to packed field is unaligned +12 | | #[repr(packed(2))] +13 | | struct PackedN { +14 | | #[pin] +15 | | field: u32, +16 | | } +17 | | } + | |_^ + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + error: borrow of packed field is unsafe and requires unsafe function or block (error E0133) --> $DIR/packed.rs:3:1 | -3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +3 | / pin_project! { //~ ERROR reference to packed field is unaligned 4 | | #[repr(packed, C)] -5 | | struct A { +5 | | struct Packed { 6 | | #[pin] 7 | | field: u16, 8 | | } @@ -13,9 +65,9 @@ error: borrow of packed field is unsafe and requires unsafe function or block (e note: the lint level is defined here --> $DIR/packed.rs:3:1 | -3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +3 | / pin_project! { //~ ERROR reference to packed field is unaligned 4 | | #[repr(packed, C)] -5 | | struct A { +5 | | struct Packed { 6 | | #[pin] 7 | | field: u16, 8 | | } @@ -29,9 +81,9 @@ note: the lint level is defined here error: borrow of packed field is unsafe and requires unsafe function or block (error E0133) --> $DIR/packed.rs:11:1 | -11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +11 | / pin_project! { //~ ERROR reference to packed field is unaligned 12 | | #[repr(packed(2))] -13 | | struct C { +13 | | struct PackedN { 14 | | #[pin] 15 | | field: u32, 16 | | } @@ -41,9 +93,9 @@ error: borrow of packed field is unsafe and requires unsafe function or block (e note: the lint level is defined here --> $DIR/packed.rs:11:1 | -11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block +11 | / pin_project! { //~ ERROR reference to packed field is unaligned 12 | | #[repr(packed(2))] -13 | | struct C { +13 | | struct PackedN { 14 | | #[pin] 15 | | field: u32, 16 | | }