Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.4: Prepare for removal of safe_packed_borrows lint #323

Merged
merged 2 commits into from
Mar 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/not_unpin-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ const _: () = {
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};

Expand Down
8 changes: 4 additions & 4 deletions examples/pinned_drop-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ const _: () = {
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<'a, T>(val: &Struct<'a, T>) {
&val.was_dropped;
&val.field;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<'a, T>(this: &Struct<'a, T>) {
let _ = &this.was_dropped;
let _ = &this.field;
}
};

Expand Down
8 changes: 4 additions & 4 deletions examples/project_replace-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ const _: () = {
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};

Expand Down
14 changes: 6 additions & 8 deletions examples/struct-default-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,19 @@ const _: () = {
// Ensure that it's impossible to use pin projections on a #[repr(packed)]
// struct.
//
// Taking a reference to a packed field is unsafe, and applying
// #[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
// circumstances, we'll detect the #[repr(packed)] attribute, and generate
// a much nicer error above.
//
// See https://github.com/taiki-e/pin-project/pull/34 for more details.
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};

Expand Down
8 changes: 4 additions & 4 deletions examples/unsafe_unpin-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ const _: () = {
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};

Expand Down
37 changes: 24 additions & 13 deletions pin-project-internal/src/pin_project/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,17 +1162,14 @@ impl<'a> Context<'a> {
}
}

// As proc-macro-derive can't rewrite the structure definition,
// it's probably no longer necessary, but it keeps it for now.

// Workaround for https://github.com/taiki-e/pin-project/issues/32
// Through the tricky use of proc macros, it's possible to bypass
// the above check for the `repr` attribute.
// To ensure that it's impossible to use pin projections on a `#[repr(packed)]`
// struct, we generate code like this:
//
// ```rust
// #[forbid(safe_packed_borrows)]
// #[forbid(unaligned_references)]
// fn assert_not_repr_packed(val: &MyStruct) {
// let _field1 = &val.field1;
// let _field2 = &val.field2;
Expand All @@ -1181,10 +1178,8 @@ impl<'a> Context<'a> {
// }
// ```
//
// Taking a reference to a packed field is unsafe, and applying
// `#[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
Expand All @@ -1204,17 +1199,33 @@ impl<'a> Context<'a> {
// `#[repr(packed)]` in the first place.
//
// See also https://github.com/taiki-e/pin-project/pull/34.
//
// Note:
// - pin-project v0.4.3 or later (ttps://github.com/taiki-e/pin-project/pull/135,
// v0.4.0-v0.4.2 are already yanked for another reason) is internally
// proc-macro-derive, so they are not affected by the problem that the
// struct definition is rewritten by another macro after the
// #[pin_project] is expanded. So this is probably no longer necessary,
// but it keeps it for now.
//
// - Lint-based tricks aren't perfect, but they're much better than nothing:
// https://github.com/taiki-e/pin-project-lite/issues/26
//
// - Forbid 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
let mut field_refs = vec![];
match fields {
Fields::Named(FieldsNamed { named, .. }) => {
for Field { ident, .. } in named {
field_refs.push(quote!(&val.#ident;));
field_refs.push(quote!(&this.#ident));
}
}
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
for (index, _) in unnamed.iter().enumerate() {
let index = Index::from(index);
field_refs.push(quote!(&val.#index;));
field_refs.push(quote!(&this.#index));
}
}
Fields::Unit => {}
Expand All @@ -1223,9 +1234,9 @@ impl<'a> Context<'a> {
let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
let ident = self.orig.ident;
Ok(quote! {
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed #impl_generics (val: &#ident #ty_generics) #where_clause {
#(#field_refs)*
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed #impl_generics (this: &#ident #ty_generics) #where_clause {
#(let _ = #field_refs;)*
}
})
}
Expand Down
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/default-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/default-tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
fn main() {}
12 changes: 6 additions & 6 deletions tests/expand/tests/expand/multifields-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned1;
&val.pinned2;
&val.unpinned1;
&val.unpinned2;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned1;
let _ = &this.pinned2;
let _ = &this.unpinned1;
let _ = &this.unpinned2;
}
};
fn main() {}
12 changes: 6 additions & 6 deletions tests/expand/tests/expand/multifields-tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
&val.2;
&val.3;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
let _ = &this.2;
let _ = &this.3;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/naming-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/naming-tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/not_unpin-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/not_unpin-tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/pinned_drop-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ const _: () = {
}
}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ const _: () = {
}
}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
Expand Down
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/project_replace-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/pub-struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
&val.pinned;
&val.unpinned;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
let _ = &this.pinned;
let _ = &this.unpinned;
}
};
fn main() {}
8 changes: 4 additions & 4 deletions tests/expand/tests/expand/pub-tuple_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ const _: () = {
impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
#[forbid(safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(val: &TupleStruct<T, U>) {
&val.0;
&val.1;
#[forbid(unaligned_references, safe_packed_borrows)]
fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
let _ = &this.0;
let _ = &this.1;
}
};
fn main() {}
Loading