diff --git a/src/lib.rs b/src/lib.rs index 81f25c9..455b692 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -425,34 +425,17 @@ macro_rules! __pin_project_internal { )? { fn drop(&mut self) { - // Safety - we're in 'drop', so we know that 'self' will - // never move again. - let pinned_self = unsafe { $crate::__private::Pin::new_unchecked(self) }; - // We call `pinned_drop` only once. Since `PinnedDrop::drop` - // is an unsafe method and a private API, it is never called again in safe - // code *unless the user uses a maliciously crafted macro*. - unsafe { - $crate::__private::PinnedDrop::drop(pinned_self); - } - } - } - impl $(< - $( $generics - $(: $generics_bound)? - $(: ?$generics_unsized_bound)? - $(: $generics_lifetime_bound)? - ),* - >)? $crate::__private::PinnedDrop for $self_ty - $(where - $( $where_clause_ty - $(: $where_clause_bound)? - $(: ?$where_clause_unsized_bound)? - $(: $where_clause_lifetime_bound)? - ),* - )? - { - unsafe fn drop(self: $crate::__private::Pin<&mut Self>) { - trait __InnerDrop { + // Implementing `__DropInner::__drop_inner` is safe, but calling it is not safe. + // This is because destructors can be called multiple times in safe code and + // [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360). + // + // `__drop_inner` is defined as a safe method, but this is fine since + // `__drop_inner` is not accessible by the users and we call `__drop_inner` only + // once. + // + // Users can implement [`Drop`] safely using `pin_project!` and can drop a + // type that implements `PinnedDrop` using the [`drop`] function safely. + trait __DropInner { fn __drop_inner(self: $crate::__private::Pin<&mut Self>); } impl $(< @@ -461,7 +444,7 @@ macro_rules! __pin_project_internal { $(: ?$generics_unsized_bound)? $(: $generics_lifetime_bound)? ),* - >)? __InnerDrop for $self_ty + >)? __DropInner for $self_ty $(where $( $where_clause_ty $(: $where_clause_bound)? @@ -474,7 +457,13 @@ macro_rules! __pin_project_internal { $($tt)* } } - __InnerDrop::__drop_inner(self); + + // Safety - we're in 'drop', so we know that 'self' will + // never move again. + let pinned_self = unsafe { $crate::__private::Pin::new_unchecked(self) }; + // We call `__drop_inner` only once. Since `__DropInner::__drop_inner` + // is not accessible by the users, it is never called again. + __DropInner::__drop_inner(pinned_self); } } }; @@ -681,24 +670,6 @@ pub mod __private { pin::Pin, }; - // Implementing `PinnedDrop::drop` is safe, but calling it is not safe. - // This is because destructors can be called multiple times in safe code and - // [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360). - // - // Ideally, it would be desirable to be able to forbid manual calls in - // the same way as [`Drop::drop`], but the library cannot do it. So, by using - // macros and replacing them with private traits, we prevent users from - // calling `PinnedDrop::drop`. - // - // Users can implement [`Drop`] safely using `#[pinned_drop]` and can drop a - // type that implements `PinnedDrop` using the [`drop`] function safely. - // **Do not call or implement this trait directly.** - #[doc(hidden)] - pub trait PinnedDrop { - #[doc(hidden)] - unsafe fn drop(self: Pin<&mut Self>); - } - // This is an internal helper struct used by `pin_project!`. #[doc(hidden)] pub struct AlwaysUnpin(PhantomData); diff --git a/tests/expand/tests/expand/pinned_drop-struct.expanded.rs b/tests/expand/tests/expand/pinned_drop-struct.expanded.rs index b04b3f3..c5aaa6f 100644 --- a/tests/expand/tests/expand/pinned_drop-struct.expanded.rs +++ b/tests/expand/tests/expand/pinned_drop-struct.expanded.rs @@ -4,6 +4,7 @@ struct Struct { pinned: T, unpinned: U, } +#[allow(explicit_outlives_requirements)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { @@ -61,29 +62,22 @@ const _: () = { } impl ::pin_project_lite::__private::Drop for Struct { fn drop(&mut self) { - let pinned_self = unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) }; - unsafe { - ::pin_project_lite::__private::PinnedDrop::drop(pinned_self); - } - } - } - impl ::pin_project_lite::__private::PinnedDrop for Struct { - unsafe fn drop(self: ::pin_project_lite::__private::Pin<&mut Self>) { - trait __InnerDrop { + trait __DropInner { fn __drop_inner(self: ::pin_project_lite::__private::Pin<&mut Self>); } - impl __InnerDrop for Struct { + impl __DropInner for Struct { fn __drop_inner(self: ::pin_project_lite::__private::Pin<&mut Self>) { let _this = self; } } - __InnerDrop::__drop_inner(self); + let pinned_self = unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) }; + __DropInner::__drop_inner(pinned_self); } } - #[deny(safe_packed_borrows)] + #[forbid(safe_packed_borrows)] fn __assert_not_repr_packed(this: &Struct) { - &this.pinned; - &this.unpinned; + let _ = &this.pinned; + let _ = &this.unpinned; } }; fn main() {}