From 060073a3e909581354897d7c17e12065bd47598c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 9 Sep 2020 22:39:55 +0900 Subject: [PATCH] Optimize code generation when used on enums When `#[pin_project]` is used on enums, only named projection types and methods are generated because there is no way to access variants of projected types without naming it. --- examples/enum-default-expanded.rs | 26 +---- pin-project-internal/src/lib.rs | 57 +++++++--- .../src/pin_project/derive.rs | 100 ++++++++++++------ tests/cfg.rs | 12 ++- .../tests/expand/default-enum.expanded.rs | 86 ++++++++------- tests/expand/tests/expand/default-enum.rs | 2 +- .../tests/expand/naming-enum-mut.expanded.rs | 31 ------ .../tests/expand/naming-enum-none.expanded.rs | 42 ++++++++ tests/expand/tests/expand/naming-enum-none.rs | 14 +++ .../tests/expand/naming-enum-own.expanded.rs | 63 ----------- .../tests/expand/naming-enum-ref.expanded.rs | 32 ------ .../expand/naming-struct-none.expanded.rs | 86 +++++++++++++++ .../expand/tests/expand/naming-struct-none.rs | 10 ++ .../naming-tuple_struct-none.expanded.rs | 74 +++++++++++++ .../tests/expand/naming-tuple_struct-none.rs | 6 ++ .../tests/expand/not_unpin-enum.expanded.rs | 86 ++++++++------- tests/expand/tests/expand/not_unpin-enum.rs | 2 +- .../tests/expand/pinned_drop-enum.expanded.rs | 86 ++++++++------- tests/expand/tests/expand/pinned_drop-enum.rs | 2 +- .../expand/project_replace-enum.expanded.rs | 95 +++-------------- .../tests/expand/project_replace-enum.rs | 2 +- .../expand/tests/expand/pub-enum.expanded.rs | 86 ++++++++------- tests/expand/tests/expand/pub-enum.rs | 2 +- .../expand/unsafe_unpin-enum.expanded.rs | 86 ++++++++------- .../expand/tests/expand/unsafe_unpin-enum.rs | 2 +- tests/include/basic-safe-part.rs | 29 ++++- tests/lint.rs | 24 ++++- tests/pin_project.rs | 18 ++-- tests/pinned_drop.rs | 2 +- tests/ui/pin_project/invalid.rs | 5 + tests/ui/pin_project/invalid.stderr | 84 ++++++++------- 31 files changed, 695 insertions(+), 557 deletions(-) create mode 100644 tests/expand/tests/expand/naming-enum-none.expanded.rs create mode 100644 tests/expand/tests/expand/naming-enum-none.rs create mode 100644 tests/expand/tests/expand/naming-struct-none.expanded.rs create mode 100644 tests/expand/tests/expand/naming-struct-none.rs create mode 100644 tests/expand/tests/expand/naming-tuple_struct-none.expanded.rs create mode 100644 tests/expand/tests/expand/naming-tuple_struct-none.rs diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs index 35dba49b..0d46ebda 100644 --- a/examples/enum-default-expanded.rs +++ b/examples/enum-default-expanded.rs @@ -41,16 +41,10 @@ where #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Pinned(::pin_project::__private::Pin<&'pin (T)>), - Unpinned(&'pin (U)), - } + // When `#[pin_project]` is used on enums, only named projection types and + // methods are generated because there is no way to access variants of + // projected types without naming it. + // (When `#[pin_project]` is used on structs, both methods are always generated.) impl Enum { fn project<'pin>( @@ -65,18 +59,6 @@ const _: () = { } } } - fn project_ref<'pin>( - self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { - unsafe { - match self.get_ref() { - Enum::Pinned(_0) => __EnumProjectionRef::Pinned( - ::pin_project::__private::Pin::new_unchecked(_0), - ), - Enum::Unpinned(_0) => __EnumProjectionRef::Unpinned(_0), - } - } - } } // Automatically create the appropriate conditional `Unpin` implementation. diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index 69ad1a53..5ca74f51 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -50,23 +50,25 @@ use proc_macro::TokenStream; /// ``` /// /// By passing an argument with the same name as the method to the attribute, -/// you can name the projection type returned from the method: +/// you can name the projection type returned from the method. This allows you +/// to use pattern matching on the projected types. /// /// ```rust -/// use pin_project::pin_project; -/// use std::pin::Pin; -/// -/// #[pin_project(project = StructProj)] -/// struct Struct { -/// #[pin] -/// field: T, +/// # use pin_project::pin_project; +/// # use std::pin::Pin; +/// #[pin_project(project = EnumProj)] +/// enum Enum { +/// Variant(#[pin] T), /// } /// -/// impl Struct { +/// impl Enum { /// fn method(self: Pin<&mut Self>) { -/// let this: StructProj<'_, T> = self.project(); -/// let StructProj { field } = this; -/// let _: Pin<&mut T> = field; +/// let this: EnumProj<'_, T> = self.project(); +/// match this { +/// EnumProj::Variant(x) => { +/// let _: Pin<&mut T> = x; +/// } +/// } /// } /// } /// ``` @@ -74,6 +76,11 @@ use proc_macro::TokenStream; /// Note that the projection types returned by `project` and `project_ref` have /// an additional lifetime at the beginning of generics. /// +/// ```text +/// let this: EnumProj<'_, T> = self.project(); +/// ^^ +/// ``` +/// /// The visibility of the projected type and projection method is based on the /// original type. However, if the visibility of the original type is `pub`, the /// visibility of the projected type and the projection method is downgraded to @@ -221,6 +228,32 @@ use proc_macro::TokenStream; /// } /// ``` /// +/// When `#[pin_project]` is used on enums, only named projection types and +/// methods are generated because there is no way to access variants of +/// projected types without naming it. +/// For example, in the above example, only `project()` method is generated, +/// and `project_ref()` method is not generated. +/// (When `#[pin_project]` is used on structs, both methods are always generated.) +/// +/// ```rust,compile_fail,E0599 +/// # use pin_project::pin_project; +/// # use std::pin::Pin; +/// # +/// # #[pin_project(project = EnumProj)] +/// # enum Enum { +/// # Tuple(#[pin] T), +/// # Struct { field: U }, +/// # Unit, +/// # } +/// # +/// impl Enum { +/// fn call_project_ref(self: Pin<&Self>) { +/// let _this = self.project_ref(); +/// //~^ ERROR no method named `project_ref` found for struct `Pin<&Enum>` in the current scope +/// } +/// } +/// ``` +/// /// If you want to call the `project()` method multiple times or later use the /// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid /// consuming the [`Pin`]. diff --git a/pin-project-internal/src/pin_project/derive.rs b/pin-project-internal/src/pin_project/derive.rs index 3555ca4c..d784eb43 100644 --- a/pin-project-internal/src/pin_project/derive.rs +++ b/pin-project-internal/src/pin_project/derive.rs @@ -610,7 +610,10 @@ impl<'a> Context<'a> { let Self #proj_pat = &mut *__self_ptr; #proj_own_body }; - generate.extend(false, self.make_proj_impl(&proj_mut_body, &proj_ref_body, &proj_own_body)); + generate.extend( + false, + self.make_proj_impl(false, &proj_mut_body, &proj_ref_body, &proj_own_body), + ); Ok(()) } @@ -620,6 +623,13 @@ impl<'a> Context<'a> { DataEnum { brace_token, variants, .. }: &DataEnum, generate: &mut GenerateTokens, ) -> Result<()> { + if let ProjReplace::Unnamed { span } = &self.project_replace { + return Err(Error::new( + *span, + "`project_replace` argument requires a value when used on enums", + )); + } + validate_enum(*brace_token, variants)?; let ProjectedVariants { @@ -641,20 +651,24 @@ impl<'a> Context<'a> { let proj_where_clause = &self.proj.where_clause; let (proj_attrs, proj_ref_attrs, proj_own_attrs) = self.proj_attrs(); - generate.extend(self.project, quote! { - #proj_attrs - #vis enum #proj_ident #proj_generics #proj_where_clause { - #proj_variants - } - }); - generate.extend(self.project_ref, quote! { - #proj_ref_attrs - #vis enum #proj_ref_ident #proj_generics #proj_where_clause { - #proj_ref_variants - } - }); - if self.project_replace.span().is_some() { - generate.extend(self.project_replace.ident().is_some(), quote! { + if self.project { + generate.extend(true, quote! { + #proj_attrs + #vis enum #proj_ident #proj_generics #proj_where_clause { + #proj_variants + } + }); + } + if self.project_ref { + generate.extend(true, quote! { + #proj_ref_attrs + #vis enum #proj_ref_ident #proj_generics #proj_where_clause { + #proj_ref_variants + } + }); + } + if self.project_replace.ident().is_some() { + generate.extend(true, quote! { #proj_own_attrs #vis enum #proj_own_ident #orig_generics #orig_where_clause { #proj_own_variants @@ -678,7 +692,10 @@ impl<'a> Context<'a> { #proj_own_arms } }; - generate.extend(false, self.make_proj_impl(&proj_mut_body, &proj_ref_body, &proj_own_body)); + generate.extend( + false, + self.make_proj_impl(true, &proj_mut_body, &proj_ref_body, &proj_own_body), + ); Ok(()) } @@ -1104,6 +1121,7 @@ impl<'a> Context<'a> { /// Creates an implementation of the projection method. fn make_proj_impl( &self, + is_enum: bool, proj_body: &TokenStream, proj_ref_body: &TokenStream, proj_own_body: &TokenStream, @@ -1119,7 +1137,25 @@ impl<'a> Context<'a> { let proj_ty_generics = self.proj.generics.split_for_impl().1; let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl(); - let replace_impl = self.project_replace.span().map(|span| { + let mut project = Some(quote! { + #vis fn project<#lifetime>( + self: ::pin_project::__private::Pin<&#lifetime mut Self>, + ) -> #proj_ident #proj_ty_generics { + unsafe { + #proj_body + } + } + }); + let mut project_ref = Some(quote! { + #vis fn project_ref<#lifetime>( + self: ::pin_project::__private::Pin<&#lifetime Self>, + ) -> #proj_ref_ident #proj_ty_generics { + unsafe { + #proj_ref_body + } + } + }); + let mut project_replace = self.project_replace.span().map(|span| { // For interoperability with `forbid(unsafe_code)`, `unsafe` token should be // call-site span. let unsafety = ::default(); @@ -1135,23 +1171,23 @@ impl<'a> Context<'a> { } }); + if is_enum { + if !self.project { + project = None; + } + if !self.project_ref { + project_ref = None; + } + if self.project_replace.ident().is_none() { + project_replace = None; + } + } + quote! { impl #impl_generics #orig_ident #ty_generics #where_clause { - #vis fn project<#lifetime>( - self: ::pin_project::__private::Pin<&#lifetime mut Self>, - ) -> #proj_ident #proj_ty_generics { - unsafe { - #proj_body - } - } - #vis fn project_ref<#lifetime>( - self: ::pin_project::__private::Pin<&#lifetime Self>, - ) -> #proj_ref_ident #proj_ty_generics { - unsafe { - #proj_ref_body - } - } - #replace_impl + #project + #project_ref + #project_replace } } } diff --git a/tests/cfg.rs b/tests/cfg.rs index 22afbe76..b75bc464 100644 --- a/tests/cfg.rs +++ b/tests/cfg.rs @@ -83,7 +83,11 @@ fn cfg() { // enums - #[pin_project(project_replace)] + #[pin_project( + project = VariantProj, + project_ref = VariantProjRef, + project_replace = VariantProjOwn, + )] enum Variant { #[cfg(target_os = "linux")] Inner(#[pin] Linux), @@ -110,7 +114,11 @@ fn cfg() { #[cfg(not(target_os = "linux"))] let _x = Variant::Other(Other); - #[pin_project(project_replace)] + #[pin_project( + project = FieldProj, + project_ref = FieldProjRef, + project_replace = FieldProjOwn, + )] enum Field { SameName { #[cfg(target_os = "linux")] diff --git a/tests/expand/tests/expand/default-enum.expanded.rs b/tests/expand/tests/expand/default-enum.expanded.rs index ff61a09e..360d1be9 100644 --- a/tests/expand/tests/expand/default-enum.expanded.rs +++ b/tests/expand/tests/expand/default-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -#[pin(__private())] +# [pin (__private (project = EnumProj , project_ref = EnumProjRef))] enum Enum { Struct { #[pin] @@ -9,72 +9,70 @@ enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::mut_mut)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { fn project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { + ) -> EnumProj<'pin, T, U> { unsafe { match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { + Enum::Struct { pinned, unpinned } => EnumProj::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, + Enum::Tuple(_0, _1) => { + EnumProj::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProj::Unit, } } } fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { + ) -> EnumProjRef<'pin, T, U> { unsafe { match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { + Enum::Struct { pinned, unpinned } => EnumProjRef::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, + Enum::Tuple(_0, _1) => { + EnumProjRef::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProjRef::Unit, } } } diff --git a/tests/expand/tests/expand/default-enum.rs b/tests/expand/tests/expand/default-enum.rs index a87438db..ff056150 100644 --- a/tests/expand/tests/expand/default-enum.rs +++ b/tests/expand/tests/expand/default-enum.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project] +#[pin_project(project = EnumProj, project_ref = EnumProjRef)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/naming-enum-mut.expanded.rs b/tests/expand/tests/expand/naming-enum-mut.expanded.rs index b1175e8e..1eee6c8a 100644 --- a/tests/expand/tests/expand/naming-enum-mut.expanded.rs +++ b/tests/expand/tests/expand/naming-enum-mut.expanded.rs @@ -29,20 +29,6 @@ where #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { fn project<'pin>(self: ::pin_project::__private::Pin<&'pin mut Self>) -> Proj<'pin, T, U> { unsafe { @@ -58,23 +44,6 @@ const _: () = { } } } - fn project_ref<'pin>( - self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { - unsafe { - match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, - } - } - } } struct __Enum<'pin, T, U> { __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< diff --git a/tests/expand/tests/expand/naming-enum-none.expanded.rs b/tests/expand/tests/expand/naming-enum-none.expanded.rs new file mode 100644 index 00000000..ac398fcd --- /dev/null +++ b/tests/expand/tests/expand/naming-enum-none.expanded.rs @@ -0,0 +1,42 @@ +use pin_project::pin_project; +#[pin(__private())] +enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} +#[doc(hidden)] +#[allow(non_upper_case_globals)] +#[allow(single_use_lifetimes)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + impl Enum {} + struct __Enum<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + ( + ::pin_project::__private::PhantomData, + ::pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for Enum where + __Enum<'pin, T, U>: ::pin_project::__private::Unpin + { + } + unsafe impl ::pin_project::UnsafeUnpin for Enum {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + impl ::pin_project::__private::PinnedDrop for Enum { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } +}; +fn main() {} diff --git a/tests/expand/tests/expand/naming-enum-none.rs b/tests/expand/tests/expand/naming-enum-none.rs new file mode 100644 index 00000000..a87438db --- /dev/null +++ b/tests/expand/tests/expand/naming-enum-none.rs @@ -0,0 +1,14 @@ +use pin_project::pin_project; + +#[pin_project] +enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +fn main() {} diff --git a/tests/expand/tests/expand/naming-enum-own.expanded.rs b/tests/expand/tests/expand/naming-enum-own.expanded.rs index e79932a3..fa15a947 100644 --- a/tests/expand/tests/expand/naming-enum-own.expanded.rs +++ b/tests/expand/tests/expand/naming-enum-own.expanded.rs @@ -25,70 +25,7 @@ enum ProjOwn { #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { - fn project<'pin>( - self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { - unsafe { - match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, - } - } - } - fn project_ref<'pin>( - self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { - unsafe { - match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, - } - } - } fn project_replace( self: ::pin_project::__private::Pin<&mut Self>, __replacement: Self, diff --git a/tests/expand/tests/expand/naming-enum-ref.expanded.rs b/tests/expand/tests/expand/naming-enum-ref.expanded.rs index aa39d6e2..d94ac78f 100644 --- a/tests/expand/tests/expand/naming-enum-ref.expanded.rs +++ b/tests/expand/tests/expand/naming-enum-ref.expanded.rs @@ -28,39 +28,7 @@ where #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } impl Enum { - fn project<'pin>( - self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { - unsafe { - match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, - } - } - } fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, ) -> ProjRef<'pin, T, U> { diff --git a/tests/expand/tests/expand/naming-struct-none.expanded.rs b/tests/expand/tests/expand/naming-struct-none.expanded.rs new file mode 100644 index 00000000..fcd47538 --- /dev/null +++ b/tests/expand/tests/expand/naming-struct-none.expanded.rs @@ -0,0 +1,86 @@ +use pin_project::pin_project; +#[pin(__private())] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[doc(hidden)] +#[allow(non_upper_case_globals)] +#[allow(single_use_lifetimes)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::mut_mut)] + #[allow(clippy::type_repetition_in_bounds)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::type_repetition_in_bounds)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + struct __Struct<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + ( + ::pin_project::__private::PhantomData, + ::pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where + __Struct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + unsafe impl ::pin_project::UnsafeUnpin for Struct {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + #[deny(safe_packed_borrows)] + fn __assert_not_repr_packed(val: &Struct) { + &val.pinned; + &val.unpinned; + } +}; +fn main() {} diff --git a/tests/expand/tests/expand/naming-struct-none.rs b/tests/expand/tests/expand/naming-struct-none.rs new file mode 100644 index 00000000..474f0a11 --- /dev/null +++ b/tests/expand/tests/expand/naming-struct-none.rs @@ -0,0 +1,10 @@ +use pin_project::pin_project; + +#[pin_project] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +fn main() {} diff --git a/tests/expand/tests/expand/naming-tuple_struct-none.expanded.rs b/tests/expand/tests/expand/naming-tuple_struct-none.expanded.rs new file mode 100644 index 00000000..b4303e55 --- /dev/null +++ b/tests/expand/tests/expand/naming-tuple_struct-none.expanded.rs @@ -0,0 +1,74 @@ +use pin_project::pin_project; +#[pin(__private())] +struct TupleStruct(#[pin] T, U); +#[doc(hidden)] +#[allow(non_upper_case_globals)] +#[allow(single_use_lifetimes)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::mut_mut)] + #[allow(clippy::type_repetition_in_bounds)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(single_use_lifetimes)] + #[allow(clippy::type_repetition_in_bounds)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + } + struct __TupleStruct<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + ( + ::pin_project::__private::PhantomData, + ::pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for TupleStruct where + __TupleStruct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + unsafe impl ::pin_project::UnsafeUnpin for TupleStruct {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + impl ::pin_project::__private::PinnedDrop for TupleStruct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + #[deny(safe_packed_borrows)] + fn __assert_not_repr_packed(val: &TupleStruct) { + &val.0; + &val.1; + } +}; +fn main() {} diff --git a/tests/expand/tests/expand/naming-tuple_struct-none.rs b/tests/expand/tests/expand/naming-tuple_struct-none.rs new file mode 100644 index 00000000..398b14f3 --- /dev/null +++ b/tests/expand/tests/expand/naming-tuple_struct-none.rs @@ -0,0 +1,6 @@ +use pin_project::pin_project; + +#[pin_project] +struct TupleStruct(#[pin] T, U); + +fn main() {} diff --git a/tests/expand/tests/expand/not_unpin-enum.expanded.rs b/tests/expand/tests/expand/not_unpin-enum.expanded.rs index 2746186f..b5a9fa10 100644 --- a/tests/expand/tests/expand/not_unpin-enum.expanded.rs +++ b/tests/expand/tests/expand/not_unpin-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -# [pin (__private (! Unpin))] +# [pin (__private (! Unpin , project = EnumProj , project_ref = EnumProjRef))] enum Enum { Struct { #[pin] @@ -9,72 +9,70 @@ enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::mut_mut)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { fn project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { + ) -> EnumProj<'pin, T, U> { unsafe { match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { + Enum::Struct { pinned, unpinned } => EnumProj::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, + Enum::Tuple(_0, _1) => { + EnumProj::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProj::Unit, } } } fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { + ) -> EnumProjRef<'pin, T, U> { unsafe { match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { + Enum::Struct { pinned, unpinned } => EnumProjRef::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, + Enum::Tuple(_0, _1) => { + EnumProjRef::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProjRef::Unit, } } } diff --git a/tests/expand/tests/expand/not_unpin-enum.rs b/tests/expand/tests/expand/not_unpin-enum.rs index aae554e8..ac0b3b80 100644 --- a/tests/expand/tests/expand/not_unpin-enum.rs +++ b/tests/expand/tests/expand/not_unpin-enum.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(!Unpin)] +#[pin_project(!Unpin, project = EnumProj, project_ref = EnumProjRef)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/pinned_drop-enum.expanded.rs b/tests/expand/tests/expand/pinned_drop-enum.expanded.rs index 579dec6a..168f7a70 100644 --- a/tests/expand/tests/expand/pinned_drop-enum.expanded.rs +++ b/tests/expand/tests/expand/pinned_drop-enum.expanded.rs @@ -1,6 +1,6 @@ use pin_project::{pin_project, pinned_drop}; use std::pin::Pin; -#[pin(__private(PinnedDrop))] +# [pin (__private (PinnedDrop , project = EnumProj , project_ref = EnumProjRef))] enum Enum { Struct { #[pin] @@ -10,72 +10,70 @@ enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::mut_mut)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { fn project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { + ) -> EnumProj<'pin, T, U> { unsafe { match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { + Enum::Struct { pinned, unpinned } => EnumProj::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, + Enum::Tuple(_0, _1) => { + EnumProj::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProj::Unit, } } } fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { + ) -> EnumProjRef<'pin, T, U> { unsafe { match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { + Enum::Struct { pinned, unpinned } => EnumProjRef::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, + Enum::Tuple(_0, _1) => { + EnumProjRef::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProjRef::Unit, } } } diff --git a/tests/expand/tests/expand/pinned_drop-enum.rs b/tests/expand/tests/expand/pinned_drop-enum.rs index 7d30abaa..003b79d5 100644 --- a/tests/expand/tests/expand/pinned_drop-enum.rs +++ b/tests/expand/tests/expand/pinned_drop-enum.rs @@ -1,7 +1,7 @@ use pin_project::{pin_project, pinned_drop}; use std::pin::Pin; -#[pin_project(PinnedDrop)] +#[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/project_replace-enum.expanded.rs b/tests/expand/tests/expand/project_replace-enum.expanded.rs index ebc7a4be..52c37025 100644 --- a/tests/expand/tests/expand/project_replace-enum.expanded.rs +++ b/tests/expand/tests/expand/project_replace-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -#[pin(__private(project_replace))] +# [pin (__private (project_replace = EnumProjOwn))] enum Enum { Struct { #[pin] @@ -9,95 +9,32 @@ enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +enum EnumProjOwn { + Struct { + pinned: ::pin_project::__private::PhantomData, + unpinned: U, + }, + Tuple(::pin_project::__private::PhantomData, U), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(unreachable_pub)] - enum __EnumProjectionOwned { - Struct { - pinned: ::pin_project::__private::PhantomData, - unpinned: U, - }, - Tuple(::pin_project::__private::PhantomData, U), - Unit, - } impl Enum { - fn project<'pin>( - self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { - unsafe { - match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, - } - } - } - fn project_ref<'pin>( - self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { - unsafe { - match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { - pinned: ::pin_project::__private::Pin::new_unchecked(pinned), - unpinned, - }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, - } - } - } fn project_replace( self: ::pin_project::__private::Pin<&mut Self>, __replacement: Self, - ) -> __EnumProjectionOwned { + ) -> EnumProjOwn { unsafe { let __self_ptr: *mut Self = self.get_unchecked_mut(); match &mut *__self_ptr { Enum::Struct { pinned, unpinned } => { - let __result = __EnumProjectionOwned::Struct { + let __result = EnumProjOwn::Struct { pinned: ::pin_project::__private::PhantomData, unpinned: ::pin_project::__private::ptr::read(unpinned), }; @@ -111,7 +48,7 @@ const _: () = { __result } Enum::Tuple(_0, _1) => { - let __result = __EnumProjectionOwned::Tuple( + let __result = EnumProjOwn::Tuple( ::pin_project::__private::PhantomData, ::pin_project::__private::ptr::read(_1), ); @@ -125,7 +62,7 @@ const _: () = { __result } Enum::Unit => { - let __result = __EnumProjectionOwned::Unit; + let __result = EnumProjOwn::Unit; let __guard = ::pin_project::__private::UnsafeOverwriteGuard { target: __self_ptr, value: ::pin_project::__private::ManuallyDrop::new(__replacement), diff --git a/tests/expand/tests/expand/project_replace-enum.rs b/tests/expand/tests/expand/project_replace-enum.rs index cb314ecb..d737f649 100644 --- a/tests/expand/tests/expand/project_replace-enum.rs +++ b/tests/expand/tests/expand/project_replace-enum.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(project_replace)] +#[pin_project(project_replace = EnumProjOwn)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/pub-enum.expanded.rs b/tests/expand/tests/expand/pub-enum.expanded.rs index d5314d41..29bc7ccb 100644 --- a/tests/expand/tests/expand/pub-enum.expanded.rs +++ b/tests/expand/tests/expand/pub-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -#[pin(__private())] +# [pin (__private (project = EnumProj , project_ref = EnumProjRef))] pub enum Enum { Struct { #[pin] @@ -9,72 +9,70 @@ pub enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::mut_mut)] +#[allow(clippy::type_repetition_in_bounds)] +pub(crate) enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::type_repetition_in_bounds)] +pub(crate) enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - pub(crate) enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - pub(crate) enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { pub(crate) fn project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { + ) -> EnumProj<'pin, T, U> { unsafe { match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { + Enum::Struct { pinned, unpinned } => EnumProj::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, + Enum::Tuple(_0, _1) => { + EnumProj::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProj::Unit, } } } pub(crate) fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { + ) -> EnumProjRef<'pin, T, U> { unsafe { match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { + Enum::Struct { pinned, unpinned } => EnumProjRef::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, + Enum::Tuple(_0, _1) => { + EnumProjRef::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProjRef::Unit, } } } diff --git a/tests/expand/tests/expand/pub-enum.rs b/tests/expand/tests/expand/pub-enum.rs index 53d00efd..7c8577fd 100644 --- a/tests/expand/tests/expand/pub-enum.rs +++ b/tests/expand/tests/expand/pub-enum.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project] +#[pin_project(project = EnumProj, project_ref = EnumProjRef)] pub enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/unsafe_unpin-enum.expanded.rs b/tests/expand/tests/expand/unsafe_unpin-enum.expanded.rs index 47800ab3..c1a8733e 100644 --- a/tests/expand/tests/expand/unsafe_unpin-enum.expanded.rs +++ b/tests/expand/tests/expand/unsafe_unpin-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::{pin_project, UnsafeUnpin}; -#[pin(__private(UnsafeUnpin))] +# [pin (__private (UnsafeUnpin , project = EnumProj , project_ref = EnumProjRef))] enum Enum { Struct { #[pin] @@ -9,72 +9,70 @@ enum Enum { Tuple(#[pin] T, U), Unit, } +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::mut_mut)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(dead_code)] +#[allow(single_use_lifetimes)] +#[allow(clippy::type_repetition_in_bounds)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} #[doc(hidden)] #[allow(non_upper_case_globals)] #[allow(single_use_lifetimes)] #[allow(clippy::used_underscore_binding)] const _: () = { - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::mut_mut)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjection<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin mut (T)>, - unpinned: &'pin mut (U), - }, - Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), - Unit, - } - #[allow(dead_code)] - #[allow(single_use_lifetimes)] - #[allow(clippy::type_repetition_in_bounds)] - enum __EnumProjectionRef<'pin, T, U> - where - Enum: 'pin, - { - Struct { - pinned: ::pin_project::__private::Pin<&'pin (T)>, - unpinned: &'pin (U), - }, - Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), - Unit, - } impl Enum { fn project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, - ) -> __EnumProjection<'pin, T, U> { + ) -> EnumProj<'pin, T, U> { unsafe { match self.get_unchecked_mut() { - Enum::Struct { pinned, unpinned } => __EnumProjection::Struct { + Enum::Struct { pinned, unpinned } => EnumProj::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjection::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjection::Unit, + Enum::Tuple(_0, _1) => { + EnumProj::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProj::Unit, } } } fn project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, - ) -> __EnumProjectionRef<'pin, T, U> { + ) -> EnumProjRef<'pin, T, U> { unsafe { match self.get_ref() { - Enum::Struct { pinned, unpinned } => __EnumProjectionRef::Struct { + Enum::Struct { pinned, unpinned } => EnumProjRef::Struct { pinned: ::pin_project::__private::Pin::new_unchecked(pinned), unpinned, }, - Enum::Tuple(_0, _1) => __EnumProjectionRef::Tuple( - ::pin_project::__private::Pin::new_unchecked(_0), - _1, - ), - Enum::Unit => __EnumProjectionRef::Unit, + Enum::Tuple(_0, _1) => { + EnumProjRef::Tuple(::pin_project::__private::Pin::new_unchecked(_0), _1) + } + Enum::Unit => EnumProjRef::Unit, } } } diff --git a/tests/expand/tests/expand/unsafe_unpin-enum.rs b/tests/expand/tests/expand/unsafe_unpin-enum.rs index c1350f61..d368d713 100644 --- a/tests/expand/tests/expand/unsafe_unpin-enum.rs +++ b/tests/expand/tests/expand/unsafe_unpin-enum.rs @@ -1,6 +1,6 @@ use pin_project::{pin_project, UnsafeUnpin}; -#[pin_project(UnsafeUnpin)] +#[pin_project(UnsafeUnpin, project = EnumProj, project_ref = EnumProjRef)] enum Enum { Struct { #[pin] diff --git a/tests/include/basic-safe-part.rs b/tests/include/basic-safe-part.rs index fefc9245..c8d24bde 100644 --- a/tests/include/basic-safe-part.rs +++ b/tests/include/basic-safe-part.rs @@ -12,7 +12,10 @@ pub struct DefaultStruct { #[derive(Debug)] pub struct DefaultTupleStruct(#[pin] pub T, pub U); -#[::pin_project::pin_project] +#[::pin_project::pin_project( + project = DefaultEnumProj, + project_ref = DefaultEnumProjRef, +)] #[derive(Debug)] pub enum DefaultEnum { Struct { @@ -46,7 +49,11 @@ impl PinnedDrop for PinnedDropTupleStruct { fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} } -#[::pin_project::pin_project(PinnedDrop)] +#[::pin_project::pin_project( + PinnedDrop, + project = PinnedDropEnumProj, + project_ref = PinnedDropEnumProjRef, +)] #[derive(Debug)] pub enum PinnedDropEnum { Struct { @@ -75,7 +82,11 @@ pub struct ReplaceStruct { #[derive(Debug)] pub struct ReplaceTupleStruct(#[pin] pub T, pub U); -#[::pin_project::pin_project(project_replace)] +#[::pin_project::pin_project( + project = ReplaceEnumProj, + project_ref = ReplaceEnumProjRef, + project_replace = ReplaceEnumProjOwn, +)] #[derive(Debug)] pub enum ReplaceEnum { Struct { @@ -99,7 +110,11 @@ pub struct UnsafeUnpinStruct { #[derive(Debug)] pub struct UnsafeUnpinTupleStruct(#[pin] pub T, pub U); -#[::pin_project::pin_project(UnsafeUnpin)] +#[::pin_project::pin_project( + UnsafeUnpin, + project = UnsafeUnpinEnumProj, + project_ref = UnsafeUnpinEnumProjRef, +)] #[derive(Debug)] pub enum UnsafeUnpinEnum { Struct { @@ -123,7 +138,11 @@ pub struct NotUnpinStruct { #[derive(Debug)] pub struct NotUnpinTupleStruct(#[pin] pub T, pub U); -#[::pin_project::pin_project(!Unpin)] +#[::pin_project::pin_project( + !Unpin, + project = NotUnpinEnumProj, + project_ref = NotUnpinEnumProjRef, +)] #[derive(Debug)] pub enum NotUnpinEnum { Struct { diff --git a/tests/lint.rs b/tests/lint.rs index e152930b..a30fc0cb 100644 --- a/tests/lint.rs +++ b/tests/lint.rs @@ -67,7 +67,11 @@ pub mod clippy { pub struct MutMutTupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U); #[rustversion::attr(before(1.37), allow(single_use_lifetimes))] // https://github.com/rust-lang/rust/issues/53738 - #[pin_project(project_replace)] + #[pin_project( + project = MutMutProjEnum, + project_ref = MutMutEnumProjRef, + project_replace = MutMutEnumProjOwn, + )] #[derive(Debug)] pub enum MutMutEnum<'a, T, U> { Struct { @@ -96,7 +100,11 @@ pub mod clippy { where Self: Sized; - #[pin_project(project_replace)] + #[pin_project( + project = TypeRepetitionInBoundsProjEnum, + project_ref = TypeRepetitionInBoundsEnumProjRef, + project_replace = TypeRepetitionInBoundsEnumProjOwn, + )] #[derive(Debug)] pub enum TypeRepetitionInBoundsEnum where @@ -111,7 +119,11 @@ pub mod clippy { Unit, } - #[pin_project(project_replace)] + #[pin_project( + project = UsedUnderscoreBindingStructProj, + project_ref = UsedUnderscoreBindingStructProjRef, + project_replace = UsedUnderscoreBindingStructProjOwn, + )] #[derive(Debug)] pub struct UsedUnderscoreBindingStruct { #[pin] @@ -119,7 +131,11 @@ pub mod clippy { pub _unpinned: U, } - #[pin_project(project_replace)] + #[pin_project( + project = UsedUnderscoreBindingEnumProj, + project_ref = UsedUnderscoreBindingEnumProjRef, + project_replace = UsedUnderscoreBindingEnumProjOwn, + )] #[derive(Debug)] pub enum UsedUnderscoreBindingEnum { Struct { diff --git a/tests/pin_project.rs b/tests/pin_project.rs index 4c6b4516..5543ef5e 100644 --- a/tests/pin_project.rs +++ b/tests/pin_project.rs @@ -62,7 +62,7 @@ fn projection() { let y: &mut i32 = s.1; assert_eq!(*y, 2); - #[pin_project(project_replace, project = EnumProj)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] #[derive(Eq, PartialEq, Debug)] enum Enum { Tuple(#[pin] A, B), @@ -121,7 +121,7 @@ fn projection() { #[test] fn enum_project_set() { - #[pin_project(project_replace, project = EnumProj)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] #[derive(Eq, PartialEq, Debug)] enum Enum { V1(#[pin] u8), @@ -158,7 +158,7 @@ fn where_clause() { where T: Copy; - #[pin_project] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum EnumWhere where T: Copy, @@ -206,7 +206,7 @@ fn where_clause_and_associated_type_field() { where I: Iterator; - #[pin_project(project_replace)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum where I: Iterator, @@ -241,7 +241,7 @@ fn move_out() { let x = Struct { f: NotCopy }; let _val: NotCopy = x.f; - #[pin_project(project_replace)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum { V(NotCopy), } @@ -305,7 +305,7 @@ fn trait_bounds_on_type_generics() { #[pin_project(project_replace)] pub struct TupleStruct<'a, T: ?Sized>(&'a mut T); - #[pin_project(project_replace)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum<'a, T: ?Sized> { V(&'a mut T), } @@ -408,7 +408,7 @@ fn lifetime_project() { unpinned: U, } - #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum { V { #[pin] @@ -466,7 +466,7 @@ fn lifetime_project_elided() { unpinned: U, } - #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum { V { #[pin] @@ -779,7 +779,7 @@ fn parse_self() { type Assoc = Self; } - #[pin_project(project_replace)] + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] enum Enum { Struct { _f1: Box, diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs index d0e799ec..100c8b50 100644 --- a/tests/pinned_drop.rs +++ b/tests/pinned_drop.rs @@ -143,7 +143,7 @@ fn self_struct() { #[rustversion::since(1.37)] // type_alias_enum_variants requires Rust 1.37 #[test] fn self_enum() { - #[pin_project(PinnedDrop)] + #[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)] pub enum Enum { Struct { f: () }, Tuple(()), diff --git a/tests/ui/pin_project/invalid.rs b/tests/ui/pin_project/invalid.rs index 47c484c1..b3301393 100644 --- a/tests/ui/pin_project/invalid.rs +++ b/tests/ui/pin_project/invalid.rs @@ -186,6 +186,11 @@ mod pin_project_argument { #[pin_project(project_replace = !)] //~ ERROR expected identifier struct ProjectReplace3(#[pin] ()); + + #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums + enum ProjectReplaceEnum { + V(#[pin] ()), + } } mod pin_project_conflict_naming { diff --git a/tests/ui/pin_project/invalid.stderr b/tests/ui/pin_project/invalid.stderr index 82585432..176b1599 100644 --- a/tests/ui/pin_project/invalid.stderr +++ b/tests/ui/pin_project/invalid.stderr @@ -244,109 +244,115 @@ error: expected identifier 187 | #[pin_project(project_replace = !)] //~ ERROR expected identifier | ^ +error: `project_replace` argument requires a value when used on enums + --> $DIR/invalid.rs:190:19 + | +190 | #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums + | ^^^^^^^^^^^^^^^ + error: name `OrigAndProj` is the same as the original type name - --> $DIR/invalid.rs:194:29 + --> $DIR/invalid.rs:199:29 | -194 | #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name +199 | #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name | ^^^^^^^^^^^ error: name `OrigAndProjRef` is the same as the original type name - --> $DIR/invalid.rs:197:33 + --> $DIR/invalid.rs:202:33 | -197 | #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name +202 | #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name | ^^^^^^^^^^^^^^ error: name `OrigAndProjOwn` is the same as the original type name - --> $DIR/invalid.rs:200:37 + --> $DIR/invalid.rs:205:37 | -200 | #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name +205 | #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name | ^^^^^^^^^^^^^^ error: name `A` is already specified by `project` argument - --> $DIR/invalid.rs:203:46 + --> $DIR/invalid.rs:208:46 | -203 | #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument +208 | #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument | ^ error: name `A` is already specified by `project` argument - --> $DIR/invalid.rs:206:50 + --> $DIR/invalid.rs:211:50 | -206 | #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument +211 | #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument | ^ error: name `A` is already specified by `project_ref` argument - --> $DIR/invalid.rs:209:54 + --> $DIR/invalid.rs:214:54 | -209 | #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument +214 | #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument | ^ error: duplicate #[pin_project] attribute - --> $DIR/invalid.rs:217:5 + --> $DIR/invalid.rs:222:5 | -217 | #[pin_project] //~ ERROR duplicate #[pin_project] attribute +222 | #[pin_project] //~ ERROR duplicate #[pin_project] attribute | ^^^^^^^^^^^^^^ error: #[pin_project] attribute may not be used on structs with zero fields - --> $DIR/invalid.rs:225:19 + --> $DIR/invalid.rs:230:19 | -225 | struct Struct {} //~ ERROR may not be used on structs with zero fields +230 | struct Struct {} //~ ERROR may not be used on structs with zero fields | ^^ error: #[pin_project] attribute may not be used on structs with zero fields - --> $DIR/invalid.rs:228:23 + --> $DIR/invalid.rs:233:23 | -228 | struct TupleStruct(); //~ ERROR may not be used on structs with zero fields +233 | struct TupleStruct(); //~ ERROR may not be used on structs with zero fields | ^^ error: #[pin_project] attribute may not be used on structs with zero fields - --> $DIR/invalid.rs:231:12 + --> $DIR/invalid.rs:236:12 | -231 | struct UnitStruct; //~ ERROR may not be used on structs with zero fields +236 | struct UnitStruct; //~ ERROR may not be used on structs with zero fields | ^^^^^^^^^^ error: #[pin_project] attribute may not be used on enums without variants - --> $DIR/invalid.rs:234:20 + --> $DIR/invalid.rs:239:20 | -234 | enum EnumEmpty {} //~ ERROR may not be used on enums without variants +239 | enum EnumEmpty {} //~ ERROR may not be used on enums without variants | ^^ error: #[pin_project] attribute may not be used on enums with discriminants - --> $DIR/invalid.rs:238:13 + --> $DIR/invalid.rs:243:13 | -238 | V = 2, //~ ERROR may not be used on enums with discriminants +243 | V = 2, //~ ERROR may not be used on enums with discriminants | ^ error: #[pin_project] attribute may not be used on enums with zero fields - --> $DIR/invalid.rs:243:9 + --> $DIR/invalid.rs:248:9 | -243 | / Unit, //~ ERROR may not be used on enums with zero fields -244 | | Tuple(), -245 | | Struct {}, +248 | / Unit, //~ ERROR may not be used on enums with zero fields +249 | | Tuple(), +250 | | Struct {}, | |__________________^ error: #[pin_project] attribute may only be used on structs or enums - --> $DIR/invalid.rs:249:5 + --> $DIR/invalid.rs:254:5 | -249 | / union Union { -250 | | //~^ ERROR may only be used on structs or enums -251 | | f: (), -252 | | } +254 | / union Union { +255 | | //~^ ERROR may only be used on structs or enums +256 | | f: (), +257 | | } | |_____^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:260:12 + --> $DIR/invalid.rs:265:12 | -260 | #[repr(packed)] +265 | #[repr(packed)] | ^^^^^^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:264:12 + --> $DIR/invalid.rs:269:12 | -264 | #[repr(packed)] +269 | #[repr(packed)] | ^^^^^^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:268:12 + --> $DIR/invalid.rs:273:12 | -268 | #[repr(packed)] +273 | #[repr(packed)] | ^^^^^^