From bc5a097dbb2392682e643d0b8336a158840951f8 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 14 Jun 2021 10:09:57 +0900 Subject: [PATCH] Support custom Drop implementation --- README.md | 5 - src/lib.rs | 113 ++++++++++++++++-- tests/expand/pinned_drop/enum.expanded.rs | 95 +++++++++++++++ tests/expand/pinned_drop/enum.rs | 22 ++++ tests/expand/pinned_drop/struct.expanded.rs | 92 ++++++++++++++ tests/expand/pinned_drop/struct.rs | 17 +++ tests/test.rs | 33 +++++ tests/ui/pinned_drop/call-drop-inner.rs | 17 +++ tests/ui/pinned_drop/call-drop-inner.stderr | 20 ++++ tests/ui/pinned_drop/conditional-drop-impl.rs | 26 ++++ .../pinned_drop/conditional-drop-impl.stderr | 38 ++++++ 11 files changed, 466 insertions(+), 12 deletions(-) create mode 100644 tests/expand/pinned_drop/enum.expanded.rs create mode 100644 tests/expand/pinned_drop/enum.rs create mode 100644 tests/expand/pinned_drop/struct.expanded.rs create mode 100644 tests/expand/pinned_drop/struct.rs create mode 100644 tests/ui/pinned_drop/call-drop-inner.rs create mode 100644 tests/ui/pinned_drop/call-drop-inner.stderr create mode 100644 tests/ui/pinned_drop/conditional-drop-impl.rs create mode 100644 tests/ui/pinned_drop/conditional-drop-impl.stderr diff --git a/README.md b/README.md index fbdc9d1..e185993 100644 --- a/README.md +++ b/README.md @@ -100,10 +100,6 @@ be useful in most cases. If you do need useful error messages, then upon error you can pass the same input to [pin-project] to receive a helpful description of the compile error. -### Different: No support for custom Drop implementation - -pin-project supports this by [`#[pinned_drop]`][pinned-drop]. - ### Different: No support for custom Unpin implementation pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin]. @@ -115,7 +111,6 @@ pin-project supports this. [`pin_project!`]: https://docs.rs/pin-project-lite/0.2/pin_project_lite/macro.pin_project.html [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin [pin-project]: https://github.com/taiki-e/pin-project -[pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin ## License diff --git a/src/lib.rs b/src/lib.rs index 93d68c9..9b69e64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,10 +82,6 @@ //! error you can pass the same input to [pin-project] to receive a helpful //! description of the compile error. //! -//! ## Different: No support for custom Drop implementation -//! -//! pin-project supports this by [`#[pinned_drop]`][pinned-drop]. -//! //! ## Different: No support for custom Unpin implementation //! //! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin]. @@ -96,7 +92,6 @@ //! //! [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin //! [pin-project]: https://github.com/taiki-e/pin-project -//! [pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop //! [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin #![no_std] @@ -331,6 +326,7 @@ macro_rules! __pin_project_internal { $field_vis:vis $field:ident: $field_ty:ty ),+ } + $(impl $($pinned_drop:tt)*)? ) => { $(#[$attrs])* $vis struct $ident $($def_generics)* @@ -374,6 +370,7 @@ macro_rules! __pin_project_internal { [make_proj_field_replace] [$ident] [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] + [$(impl $($pinned_drop)*)?] { $( $(#[$pin])? @@ -422,6 +419,7 @@ macro_rules! __pin_project_internal { [make_proj_field_replace] [$ident] [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] + [$(impl $($pinned_drop)*)?] { $( $(#[$pin])? @@ -484,6 +482,7 @@ macro_rules! __pin_project_internal { $crate::__pin_project_internal! { @make_drop_impl; [$ident] [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] + $(impl $($pinned_drop)*)? } // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. @@ -538,6 +537,7 @@ macro_rules! __pin_project_internal { })? ),+ } + $(impl $($pinned_drop:tt)*)? ) => { $(#[$attrs])* $vis enum $ident $($def_generics)* @@ -594,6 +594,7 @@ macro_rules! __pin_project_internal { [make_proj_field_replace] [$ident] [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] + [$(impl $($pinned_drop)*)?] { $( $variant $({ @@ -682,6 +683,7 @@ macro_rules! __pin_project_internal { $crate::__pin_project_internal! { @make_drop_impl; [$ident] [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?] + $(impl $($pinned_drop)*)? } // We don't need to check for '#[repr(packed)]', @@ -765,6 +767,7 @@ macro_rules! __pin_project_internal { [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [$(impl $($pinned_drop:tt)*)?] $($field:tt)* ) => {}; (@struct=>make_proj_replace_ty=>unnamed; @@ -773,15 +776,16 @@ macro_rules! __pin_project_internal { [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [$(impl $($pinned_drop:tt)*)?] $($field:tt)* - ) => { - }; + ) => {}; (@struct=>make_proj_replace_ty=>named; [$proj_vis:vis] [$proj_ty_ident:ident] [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [] { $( $(#[$pin:ident])? @@ -811,6 +815,7 @@ macro_rules! __pin_project_internal { [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [$(impl $($pinned_drop:tt)*)?] $($field:tt)* ) => {}; // ============================================================================================= @@ -872,6 +877,7 @@ macro_rules! __pin_project_internal { [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [] { $( $variant:ident $({ @@ -909,6 +915,7 @@ macro_rules! __pin_project_internal { [$make_proj_field:ident] [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] + [$(impl $($pinned_drop:tt)*)?] $($variant:tt)* ) => {}; @@ -1193,6 +1200,90 @@ macro_rules! __pin_project_internal { // ============================================================================================= // make_drop_impl + (@make_drop_impl; + [$_ident:ident] + [$($_impl_generics:tt)*] [$($_ty_generics:tt)*] [$(where $($_where_clause:tt)* )?] + impl $(< + $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)? + $( $generics:ident + $(: $generics_bound:path)? + $(: ?$generics_unsized_bound:path)? + $(: $generics_lifetime_bound:lifetime)? + ),* + >)? PinnedDrop for $self_ty:ty + $(where + $( $where_clause_ty:ty + $(: $where_clause_bound:path)? + $(: ?$where_clause_unsized_bound:path)? + $(: $where_clause_lifetime_bound:lifetime)? + ),* + )? + { + fn drop($($arg:ident)+: Pin<&mut Self>) { + $($tt:tt)* + } + } + ) => { + impl $(< + $( $lifetime $(: $lifetime_bound)? ,)* + $( $generics + $(: $generics_bound)? + $(: ?$generics_unsized_bound)? + $(: $generics_lifetime_bound)? + ),* + >)? $crate::__private::Drop for $self_ty + $(where + $( $where_clause_ty + $(: $where_clause_bound)? + $(: ?$where_clause_unsized_bound)? + $(: $where_clause_lifetime_bound)? + ),* + )? + { + fn drop(&mut self) { + // 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. + fn __drop_inner $(< + $( $lifetime $(: $lifetime_bound)? ,)* + $( $generics + $(: $generics_bound)? + $(: ?$generics_unsized_bound)? + $(: $generics_lifetime_bound)? + ),* + >)? ( + $($arg)+: $crate::__private::Pin<&mut $self_ty>, + ) + $(where + $( $where_clause_ty + $(: $where_clause_bound)? + $(: ?$where_clause_unsized_bound)? + $(: $where_clause_lifetime_bound)? + ),* + )? + { + // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`. + fn __drop_inner() {} + $($tt)* + } + + // Safety - we're in 'drop', so we know that 'self' will + // never move again. + let pinned_self: $crate::__private::Pin<&mut 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. + __drop_inner(pinned_self); + } + } + }; (@make_drop_impl; [$ident:ident] [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?] @@ -1414,6 +1505,7 @@ macro_rules! __pin_project_internal { $field_vis:vis $field:ident: $field_ty:ty ),+ $(,)? } + $(impl $($pinned_drop:tt)*)? ) => { $crate::__pin_project_internal! { @struct=>internal; [$($proj_mut_ident)?] @@ -1450,6 +1542,7 @@ macro_rules! __pin_project_internal { $field_vis $field: $field_ty ),+ } + $(impl $($pinned_drop)*)? } }; ( @@ -1480,6 +1573,7 @@ macro_rules! __pin_project_internal { $field_vis:vis $field:ident: $field_ty:ty ),+ $(,)? } + $(impl $($pinned_drop:tt)*)? ) => { $crate::__pin_project_internal! { @struct=>internal; [$($proj_mut_ident)?] @@ -1516,6 +1610,7 @@ macro_rules! __pin_project_internal { $field_vis $field: $field_ty ),+ } + $(impl $($pinned_drop)*)? } }; // enum @@ -1552,6 +1647,7 @@ macro_rules! __pin_project_internal { })? ),+ $(,)? } + $(impl $($pinned_drop:tt)*)? ) => { $crate::__pin_project_internal! { @enum=>internal; [$($proj_mut_ident)?] @@ -1593,6 +1689,7 @@ macro_rules! __pin_project_internal { })? ),+ } + $(impl $($pinned_drop)*)? } }; ( @@ -1628,6 +1725,7 @@ macro_rules! __pin_project_internal { })? ),+ $(,)? } + $(impl $($pinned_drop:tt)*)? ) => { $crate::__pin_project_internal! { @enum=>internal; [$($proj_mut_ident)?] @@ -1669,6 +1767,7 @@ macro_rules! __pin_project_internal { })? ),+ } + $(impl $($pinned_drop)*)? } }; } diff --git a/tests/expand/pinned_drop/enum.expanded.rs b/tests/expand/pinned_drop/enum.expanded.rs new file mode 100644 index 0000000..665ff63 --- /dev/null +++ b/tests/expand/pinned_drop/enum.expanded.rs @@ -0,0 +1,95 @@ +use pin_project_lite::pin_project; +use std::pin::Pin; +enum Enum { + Struct { pinned: T, unpinned: U }, + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::mut_mut)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::ref_option_ref)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProj<'__pin, T, U> +where + Enum: '__pin, +{ + Struct { + pinned: ::pin_project_lite::__private::Pin<&'__pin mut (T)>, + unpinned: &'__pin mut (U), + }, + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::mut_mut)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::ref_option_ref)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProjRef<'__pin, T, U> +where + Enum: '__pin, +{ + Struct { + pinned: ::pin_project_lite::__private::Pin<&'__pin (T)>, + unpinned: &'__pin (U), + }, + Unit, +} +#[allow(single_use_lifetimes)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + impl Enum { + fn project<'__pin>( + self: ::pin_project_lite::__private::Pin<&'__pin mut Self>, + ) -> EnumProj<'__pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => EnumProj::Struct { + pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned), + unpinned: unpinned, + }, + Self::Unit => EnumProj::Unit, + } + } + } + fn project_ref<'__pin>( + self: ::pin_project_lite::__private::Pin<&'__pin Self>, + ) -> EnumProjRef<'__pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => EnumProjRef::Struct { + pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned), + unpinned: unpinned, + }, + Self::Unit => EnumProjRef::Unit, + } + } + } + } + #[allow(non_snake_case)] + struct __Origin<'__pin, T, U> { + __dummy_lifetime: ::pin_project_lite::__private::PhantomData<&'__pin ()>, + Struct: (T, ::pin_project_lite::__private::AlwaysUnpin), + Unit: (), + } + impl<'__pin, T, U> ::pin_project_lite::__private::Unpin for Enum where + __Origin<'__pin, T, U>: ::pin_project_lite::__private::Unpin + { + } + impl ::pin_project_lite::__private::Drop for Enum { + fn drop(&mut self) { + fn __drop_inner(this: ::pin_project_lite::__private::Pin<&mut Enum>) { + fn __drop_inner() {} + let _ = this; + } + let pinned_self: ::pin_project_lite::__private::Pin<&mut Self> = + unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) }; + __drop_inner(pinned_self); + } + } +}; +fn main() {} diff --git a/tests/expand/pinned_drop/enum.rs b/tests/expand/pinned_drop/enum.rs new file mode 100644 index 0000000..1855cb7 --- /dev/null +++ b/tests/expand/pinned_drop/enum.rs @@ -0,0 +1,22 @@ +use pin_project_lite::pin_project; +use std::pin::Pin; + +pin_project! { + #[project = EnumProj] + #[project_ref = EnumProjRef] + enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Unit, + } + impl PinnedDrop for Enum { + fn drop(this: Pin<&mut Self>) { + let _ = this; + } + } +} + +fn main() {} diff --git a/tests/expand/pinned_drop/struct.expanded.rs b/tests/expand/pinned_drop/struct.expanded.rs new file mode 100644 index 0000000..5b82b7a --- /dev/null +++ b/tests/expand/pinned_drop/struct.expanded.rs @@ -0,0 +1,92 @@ +use pin_project_lite::pin_project; +use std::pin::Pin; +struct Struct { + pinned: T, + unpinned: U, +} +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::unknown_clippy_lints)] + #[allow(clippy::mut_mut)] + #[allow(clippy::redundant_pub_crate)] + #[allow(clippy::ref_option_ref)] + #[allow(clippy::type_repetition_in_bounds)] + struct Projection<'__pin, T, U> + where + Struct: '__pin, + { + pinned: ::pin_project_lite::__private::Pin<&'__pin mut (T)>, + unpinned: &'__pin mut (U), + } + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::unknown_clippy_lints)] + #[allow(clippy::mut_mut)] + #[allow(clippy::redundant_pub_crate)] + #[allow(clippy::ref_option_ref)] + #[allow(clippy::type_repetition_in_bounds)] + struct ProjectionRef<'__pin, T, U> + where + Struct: '__pin, + { + pinned: ::pin_project_lite::__private::Pin<&'__pin (T)>, + unpinned: &'__pin (U), + } + impl Struct { + fn project<'__pin>( + self: ::pin_project_lite::__private::Pin<&'__pin mut Self>, + ) -> Projection<'__pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + Projection { + pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned), + unpinned: unpinned, + } + } + } + fn project_ref<'__pin>( + self: ::pin_project_lite::__private::Pin<&'__pin Self>, + ) -> ProjectionRef<'__pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + ProjectionRef { + pinned: ::pin_project_lite::__private::Pin::new_unchecked(pinned), + unpinned: unpinned, + } + } + } + } + #[allow(non_snake_case)] + struct __Origin<'__pin, T, U> { + __dummy_lifetime: ::pin_project_lite::__private::PhantomData<&'__pin ()>, + pinned: T, + unpinned: ::pin_project_lite::__private::AlwaysUnpin, + } + impl<'__pin, T, U> ::pin_project_lite::__private::Unpin for Struct where + __Origin<'__pin, T, U>: ::pin_project_lite::__private::Unpin + { + } + impl ::pin_project_lite::__private::Drop for Struct { + fn drop(&mut self) { + fn __drop_inner(this: ::pin_project_lite::__private::Pin<&mut Struct>) { + fn __drop_inner() {} + let _ = this; + } + let pinned_self: ::pin_project_lite::__private::Pin<&mut Self> = + unsafe { ::pin_project_lite::__private::Pin::new_unchecked(self) }; + __drop_inner(pinned_self); + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } +}; +fn main() {} diff --git a/tests/expand/pinned_drop/struct.rs b/tests/expand/pinned_drop/struct.rs new file mode 100644 index 0000000..0cc7567 --- /dev/null +++ b/tests/expand/pinned_drop/struct.rs @@ -0,0 +1,17 @@ +use pin_project_lite::pin_project; +use std::pin::Pin; + +pin_project! { + struct Struct { + #[pin] + pinned: T, + unpinned: U, + } + impl PinnedDrop for Struct { + fn drop(this: Pin<&mut Self>) { + let _ = this; + } + } +} + +fn main() {} diff --git a/tests/test.rs b/tests/test.rs index d792bab..ceb566b 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -633,3 +633,36 @@ fn attrs() { } } } + +#[test] +fn pinned_drop() { + pin_project! { + pub struct Struct1<'a> { + was_dropped: &'a mut bool, + #[pin] + field: u8, + } + impl PinnedDrop for Struct1<'_> { + fn drop(this: Pin<&mut Self>) { + **this.project().was_dropped = true; + } + } + } + + let mut was_dropped = false; + drop(Struct1 { was_dropped: &mut was_dropped, field: 42 }); + assert!(was_dropped); + + pin_project! { + pub struct Struct2<'a> { + was_dropped: &'a mut bool, + #[pin] + field: u8, + } + impl PinnedDrop for Struct2<'_> { + fn drop(mut this: Pin<&mut Self>) { + **this.as_mut().project().was_dropped = true; + } + } + } +} diff --git a/tests/ui/pinned_drop/call-drop-inner.rs b/tests/ui/pinned_drop/call-drop-inner.rs new file mode 100644 index 0000000..609b3be --- /dev/null +++ b/tests/ui/pinned_drop/call-drop-inner.rs @@ -0,0 +1,17 @@ +use pin_project_lite::pin_project; + +pin_project! { + pub struct S { + #[pin] + field: u8, + } + impl PinnedDrop for S { + fn drop(this: Pin<&mut Self>) { + __drop_inner(this); + } + } +} + +fn main() { + let _x = S { field: 0 }; +} diff --git a/tests/ui/pinned_drop/call-drop-inner.stderr b/tests/ui/pinned_drop/call-drop-inner.stderr new file mode 100644 index 0000000..576e417 --- /dev/null +++ b/tests/ui/pinned_drop/call-drop-inner.stderr @@ -0,0 +1,20 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/call-drop-inner.rs:10:13 + | +10 | __drop_inner(this); + | ^^^^^^^^^^^^ ---- supplied 1 argument + | | + | expected 0 arguments + | +note: function defined here + --> $DIR/call-drop-inner.rs:3:1 + | +3 | / pin_project! { +4 | | pub struct S { +5 | | #[pin] +6 | | field: u8, +... | +12 | | } +13 | | } + | |_^ + = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pinned_drop/conditional-drop-impl.rs b/tests/ui/pinned_drop/conditional-drop-impl.rs new file mode 100644 index 0000000..68b01b2 --- /dev/null +++ b/tests/ui/pinned_drop/conditional-drop-impl.rs @@ -0,0 +1,26 @@ +use pin_project_lite::pin_project; + +// In `Drop` impl, the implementor must specify the same requirement as type definition. + +struct DropImpl { + f: T, +} + +impl Drop for DropImpl { + //~^ ERROR E0367 + fn drop(&mut self) {} +} + +pin_project! { + //~^ ERROR E0367 + struct PinnedDropImpl { + #[pin] + f: T, + } + + impl PinnedDrop for PinnedDropImpl { + fn drop(_this: Pin<&mut Self>) {} + } +} + +fn main() {} diff --git a/tests/ui/pinned_drop/conditional-drop-impl.stderr b/tests/ui/pinned_drop/conditional-drop-impl.stderr new file mode 100644 index 0000000..a67bc8d --- /dev/null +++ b/tests/ui/pinned_drop/conditional-drop-impl.stderr @@ -0,0 +1,38 @@ +error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not + --> $DIR/conditional-drop-impl.rs:9:9 + | +9 | impl Drop for DropImpl { + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/conditional-drop-impl.rs:5:1 + | +5 | / struct DropImpl { +6 | | f: T, +7 | | } + | |_^ + +error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not + --> $DIR/conditional-drop-impl.rs:14:1 + | +14 | / pin_project! { +15 | | //~^ ERROR E0367 +16 | | struct PinnedDropImpl { +17 | | #[pin] +... | +23 | | } +24 | | } + | |_^ + | +note: the implementor must specify the same requirement + --> $DIR/conditional-drop-impl.rs:14:1 + | +14 | / pin_project! { +15 | | //~^ ERROR E0367 +16 | | struct PinnedDropImpl { +17 | | #[pin] +... | +23 | | } +24 | | } + | |_^ + = note: this error originates in the macro `$crate::__pin_project_internal` (in Nightly builds, run with -Z macro-backtrace for more info)