diff --git a/README.md b/README.md index 1a55eee4..9c1952c8 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ struct Struct { } impl Struct { - fn foo(mut self: Pin<&mut Self>) { + fn foo(self: Pin<&mut Self>) { let this = self.project(); let _: Pin<&mut T> = this.pinned; // Pinned reference to the field let _: &mut U = this.unpinned; // Normal reference to the field diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs index a8013408..56bf694b 100644 --- a/examples/enum-default-expanded.rs +++ b/examples/enum-default-expanded.rs @@ -30,18 +30,8 @@ enum __EnumProjection<'_pin, T, U> { Unpinned(&'_pin mut U), } -impl<'_outer_pin, T, U> __EnumProjectionTrait<'_outer_pin, T, U> - for ::core::pin::Pin<&'_outer_pin mut Enum> -{ - fn project<'_pin>(&'_pin mut self) -> __EnumProjection<'_pin, T, U> { - unsafe { - match self.as_mut().get_unchecked_mut() { - Enum::Pinned(_x0) => __EnumProjection::Pinned(::core::pin::Pin::new_unchecked(_x0)), - Enum::Unpinned(_x0) => __EnumProjection::Unpinned(_x0), - } - } - } - fn project_into(self) -> __EnumProjection<'_outer_pin, T, U> { +impl Enum { + fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __EnumProjection<'_pin, T, U> { unsafe { match self.get_unchecked_mut() { Enum::Pinned(_x0) => __EnumProjection::Pinned(::core::pin::Pin::new_unchecked(_x0)), @@ -51,11 +41,6 @@ impl<'_outer_pin, T, U> __EnumProjectionTrait<'_outer_pin, T, U> } } -trait __EnumProjectionTrait<'_outer_pin, T, U> { - fn project<'_pin>(&'_pin mut self) -> __EnumProjection<'_pin, T, U>; - fn project_into(self) -> __EnumProjection<'_outer_pin, T, U>; -} - // Automatically create the appropriate conditional `Unpin` implementation. // // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs index f393f848..5ae3798f 100644 --- a/examples/pinned_drop-expanded.rs +++ b/examples/pinned_drop-expanded.rs @@ -38,19 +38,8 @@ struct __FooProjection<'_pin, 'a, T> { field: ::core::pin::Pin<&'_pin mut T>, } -impl<'_outer_pin, 'a, T> __FooProjectionTrait<'_outer_pin, 'a, T> - for ::core::pin::Pin<&'_outer_pin mut Foo<'a, T>> -{ - fn project<'_pin>(&'_pin mut self) -> __FooProjection<'_pin, 'a, T> { - unsafe { - let Foo { was_dropped, field } = self.as_mut().get_unchecked_mut(); - __FooProjection { - was_dropped: was_dropped, - field: ::core::pin::Pin::new_unchecked(field), - } - } - } - fn project_into(self) -> __FooProjection<'_outer_pin, 'a, T> { +impl<'a, T> Foo<'a, T> { + fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __FooProjection<'_pin, 'a, T> { unsafe { let Foo { was_dropped, field } = self.get_unchecked_mut(); __FooProjection { @@ -61,11 +50,6 @@ impl<'_outer_pin, 'a, T> __FooProjectionTrait<'_outer_pin, 'a, T> } } -trait __FooProjectionTrait<'_outer_pin, 'a, T> { - fn project<'_pin>(&'_pin mut self) -> __FooProjection<'_pin, 'a, T>; - fn project_into(self) -> __FooProjection<'_outer_pin, 'a, T>; -} - #[allow(single_use_lifetimes)] impl<'a, T> ::core::ops::Drop for Foo<'a, T> { fn drop(&mut self) { @@ -95,7 +79,7 @@ impl<'a, T> ::core::ops::Drop for Foo<'a, T> { impl ::pin_project::__private::PinnedDrop for Foo<'_, T> { // Since calling it twice on the same object would be UB, // this method is unsafe. - unsafe fn drop(mut self: ::core::pin::Pin<&mut Self>) { + unsafe fn drop(self: Pin<&mut Self>) { **self.project().was_dropped = true; } } diff --git a/examples/pinned_drop.rs b/examples/pinned_drop.rs index 98f3c48a..87bb59c0 100644 --- a/examples/pinned_drop.rs +++ b/examples/pinned_drop.rs @@ -14,7 +14,7 @@ pub struct Foo<'a, T> { #[pinned_drop] impl PinnedDrop for Foo<'_, T> { - fn drop(mut self: Pin<&mut Self>) { + fn drop(self: Pin<&mut Self>) { **self.project().was_dropped = true; } } diff --git a/examples/struct-default-expanded.rs b/examples/struct-default-expanded.rs index d9cc2281..dc6b9d1d 100644 --- a/examples/struct-default-expanded.rs +++ b/examples/struct-default-expanded.rs @@ -31,19 +31,8 @@ struct __StructProjection<'_pin, T, U> { unpinned: &'_pin mut U, } -impl<'_outer_pin, T, U> __StructProjectionTrait<'_outer_pin, T, U> - for ::core::pin::Pin<&'_outer_pin mut Struct> -{ - fn project<'_pin>(&'_pin mut self) -> __StructProjection<'_pin, T, U> { - unsafe { - let Struct { pinned, unpinned } = self.as_mut().get_unchecked_mut(); - __StructProjection { - pinned: ::core::pin::Pin::new_unchecked(pinned), - unpinned: unpinned, - } - } - } - fn project_into(self) -> __StructProjection<'_outer_pin, T, U> { +impl Struct { + fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __StructProjection<'_pin, T, U> { unsafe { let Struct { pinned, unpinned } = self.get_unchecked_mut(); __StructProjection { @@ -54,11 +43,6 @@ impl<'_outer_pin, T, U> __StructProjectionTrait<'_outer_pin, T, U> } } -trait __StructProjectionTrait<'_outer_pin, T, U> { - fn project<'_pin>(&'_pin mut self) -> __StructProjection<'_pin, T, U>; - fn project_into(self) -> __StructProjection<'_outer_pin, T, U>; -} - // Automatically create the appropriate conditional `Unpin` implementation. // // Basically this is equivalent to the following code: diff --git a/examples/unsafe_unpin-expanded.rs b/examples/unsafe_unpin-expanded.rs index 69f8568c..ff9f1c58 100644 --- a/examples/unsafe_unpin-expanded.rs +++ b/examples/unsafe_unpin-expanded.rs @@ -33,16 +33,8 @@ struct __FooProjection<'_pin, T, U> { unpinned: &'_pin mut U, } -impl<'_outer_pin, T, U> __FooProjectionTrait<'_outer_pin, T, U> - for ::core::pin::Pin<&'_outer_pin mut Foo> -{ - fn project<'_pin>(&'_pin mut self) -> __FooProjection<'_pin, T, U> { - unsafe { - let Foo { pinned, unpinned } = self.as_mut().get_unchecked_mut(); - __FooProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned: unpinned } - } - } - fn project_into(self) -> __FooProjection<'_outer_pin, T, U> { +impl Foo { + fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __FooProjection<'_pin, T, U> { unsafe { let Foo { pinned, unpinned } = self.get_unchecked_mut(); __FooProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned: unpinned } @@ -50,11 +42,6 @@ impl<'_outer_pin, T, U> __FooProjectionTrait<'_outer_pin, T, U> } } -trait __FooProjectionTrait<'_outer_pin, T, U> { - fn project<'_pin>(&'_pin mut self) -> __FooProjection<'_pin, T, U>; - fn project_into(self) -> __FooProjection<'_outer_pin, T, U>; -} - unsafe impl UnsafeUnpin for Foo {} impl ::core::marker::Unpin for Foo where diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index a29c026f..733f45c9 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -34,45 +34,20 @@ use syn::parse::Nothing; /// the field. /// - For the other fields, makes the unpinned reference to the field. /// -/// The following methods are implemented on the original `#[pin_project]` type: +/// The following method is implemented on the original `#[pin_project]` type: /// /// ``` /// # #![feature(arbitrary_self_types)] /// # use std::pin::Pin; /// # type ProjectedType = (); -/// # trait ProjectionTrait { -/// fn project(self: &mut Pin<&mut Self>) -> ProjectedType; -/// fn project_into(self: Pin<&mut Self>) -> ProjectedType; +/// # trait Projection { +/// fn project(self: Pin<&mut Self>) -> ProjectedType; /// # } /// ``` /// -/// The `project` method takes a mutable reference to a pinned -/// type, and returns a projection struct. This is the method -/// you'll usually want to use - since it takes a mutable reference, -/// it can be called multiple times, and allows you to use -/// the original Pin type later on (e.g. to call [`Pin::set`]). -/// -/// The `project_into` type takes a pinned type by value (consuming it), -/// and returns a projection struct. The difference between this and the `project` -/// method lies in the lifetime. While the type returned by `project` only lives -/// as long as the 'outer' mutable reference, the type returned by this method -/// lives for as long as the original Pin. This can be useful when returning a pin -/// projection from a method: -/// -/// ``` -/// # use pin_project::pin_project; -/// # use std::pin::Pin; -/// # #[pin_project] -/// # struct Struct { -/// # #[pin] -/// # pinned: T, -/// # } -/// # impl Struct { -/// fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { -/// self.project_into().pinned -/// } -/// # } -/// ``` +/// 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`. /// /// ## Safety /// @@ -147,7 +122,7 @@ use syn::parse::Nothing; /// } /// /// impl Foo { -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// let this = self.project(); /// let _: Pin<&mut T> = this.future; // Pinned reference to the field /// let _: &mut U = this.field; // Normal reference to the field @@ -170,7 +145,7 @@ use syn::parse::Nothing; /// } /// /// impl Foo { -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// let this = self.project(); /// let _: Pin<&mut T> = this.future; // Pinned reference to the field /// let _: &mut U = this.field; // Normal reference to the field @@ -259,7 +234,7 @@ use syn::parse::Nothing; /// } /// /// impl Foo { -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// let this = self.project(); /// let _: Pin<&mut T> = this.future; /// let _: &mut U = this.field; @@ -277,7 +252,7 @@ use syn::parse::Nothing; /// struct Foo(#[pin] T, U); /// /// impl Foo { -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// let this = self.project(); /// let _: Pin<&mut T> = this.0; /// let _: &mut U = this.1; @@ -316,7 +291,7 @@ use syn::parse::Nothing; /// # #[cfg(feature = "project_attr")] /// impl Foo { /// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// #[project] /// match self.project() { /// Foo::Tuple(x, y) => { @@ -422,7 +397,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// /// // impl for the original type /// impl Foo { -/// fn bar(mut self: Pin<&mut Self>) { +/// fn bar(self: Pin<&mut Self>) { /// self.project().baz() /// } /// } @@ -459,7 +434,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// /// impl Foo { /// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// #[project] /// let Foo { future, field } = self.project(); /// @@ -489,7 +464,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// /// impl Foo { /// #[project] // Nightly does not need a dummy attribute to the function. -/// fn baz(mut self: Pin<&mut Self>) { +/// fn baz(self: Pin<&mut Self>) { /// #[project] /// match self.project() { /// Foo::Tuple(x, y) => { diff --git a/pin-project-internal/src/pin_project/attribute.rs b/pin-project-internal/src/pin_project/attribute.rs index b82a6a40..c7382fcb 100644 --- a/pin-project-internal/src/pin_project/attribute.rs +++ b/pin-project-internal/src/pin_project/attribute.rs @@ -7,44 +7,42 @@ use syn::{ }; use crate::utils::{ - self, collect_cfg, crate_path, proj_ident, proj_lifetime_name, proj_trait_ident, VecExt, - DEFAULT_LIFETIME_NAME, TRAIT_LIFETIME_NAME, + self, collect_cfg, crate_path, proj_ident, proj_lifetime_name, VecExt, DEFAULT_LIFETIME_NAME, }; use super::PIN; -pub(super) fn parse_attribute(args: TokenStream, input: Item) -> Result { - match input { - Item::Struct(mut item) => { - let mut cx = - Context::new(args, &mut item.attrs, item.ident.clone(), item.generics.clone())?; +pub(super) fn parse_attribute(args: TokenStream, mut item: Item) -> Result { + let cx; + let proj_items = match &mut item { + Item::Struct(item) => { + cx = Context::new(args, &mut item.attrs, &item.ident, &item.generics)?; let packed_check = ensure_not_packed(&item)?; - let proj_items = cx.parse_struct(&mut item)?; - let mut item = item.into_token_stream(); - item.extend(proj_items); - item.extend(cx.make_proj_trait()); - item.extend(cx.make_unpin_impl()); - item.extend(cx.make_drop_impl()); - item.extend(packed_check); - Ok(item) + let mut proj_items = cx.parse_struct(item)?; + proj_items.extend(packed_check); + proj_items } - Item::Enum(mut item) => { - let mut cx = - Context::new(args, &mut item.attrs, item.ident.clone(), item.generics.clone())?; + Item::Enum(item) => { + cx = Context::new(args, &mut item.attrs, &item.ident, &item.generics)?; // We don't need to check for '#[repr(packed)]', // since it does not apply to enums. - let proj_items = cx.parse_enum(&mut item)?; - let mut item = item.into_token_stream(); - item.extend(proj_items); - item.extend(cx.make_proj_trait()); - item.extend(cx.make_unpin_impl()); - item.extend(cx.make_drop_impl()); - Ok(item) + cx.parse_enum(item)? } - item => Err(error!(item, "#[pin_project] attribute may only be used on structs or enums")), - } + _ => { + return Err(error!( + item, + "#[pin_project] attribute may only be used on structs or enums" + )); + } + }; + + let mut item = item.into_token_stream(); + item.extend(proj_items); + item.extend(cx.make_unpin_impl()); + item.extend(cx.make_drop_impl()); + Ok(item) } #[allow(dead_code)] // https://github.com/rust-lang/rust/issues/56750 @@ -98,18 +96,12 @@ struct Context { /// Name of the projected type. proj_ident: Ident, - /// Name of the trait generated to provide a 'project' method. - proj_trait: Ident, - /// Generics of the original type. generics: Generics, /// Lifetime on the generated projected type. lifetime: Lifetime, - /// Lifetime on the generated projection trait. - trait_lifetime: Lifetime, - /// `UnsafeUnpin` attribute. unsafe_unpin: Option, @@ -121,8 +113,8 @@ impl Context { fn new( args: TokenStream, attrs: &mut Vec, - orig_ident: Ident, - generics: Generics, + orig_ident: &Ident, + generics: &Generics, ) -> Result { let Args { pinned_drop, unsafe_unpin } = syn::parse2(args)?; @@ -133,25 +125,16 @@ impl Context { ); } - let proj_ident = proj_ident(&orig_ident); - let proj_trait = proj_trait_ident(&orig_ident); - let mut lifetime_name = String::from(DEFAULT_LIFETIME_NAME); proj_lifetime_name(&mut lifetime_name, &generics.params); let lifetime = Lifetime::new(&lifetime_name, Span::call_site()); - let mut trait_lifetime_name = String::from(TRAIT_LIFETIME_NAME); - proj_lifetime_name(&mut trait_lifetime_name, &generics.params); - let trait_lifetime = Lifetime::new(&trait_lifetime_name, Span::call_site()); - Ok(Self { crate_path, - orig_ident, - proj_ident, - proj_trait, - generics, + orig_ident: orig_ident.clone(), + proj_ident: proj_ident(orig_ident), + generics: generics.clone(), lifetime, - trait_lifetime, unsafe_unpin, pinned_drop, }) @@ -164,13 +147,6 @@ impl Context { generics } - /// Creates the generics for the 'project_into' method. - fn project_into_generics(&self) -> Generics { - let mut generics = self.generics.clone(); - utils::proj_generics(&mut generics, self.trait_lifetime.clone()); - generics - } - fn find_pin_attr(&self, attrs: &mut Vec) -> Result { if let Some(pos) = attrs.position(PIN) { let tokens = if self.unsafe_unpin.is_some() { @@ -280,53 +256,22 @@ impl Context { } } - /// Creates a definition of the projection trait. - fn make_proj_trait(&self) -> TokenStream { - let Self { proj_ident, proj_trait, lifetime, .. } = self; - let proj_generics = self.proj_generics(); - let proj_ty_generics = proj_generics.split_for_impl().1; - - // Add trait lifetime to trait generics. - let mut trait_generics = self.generics.clone(); - utils::proj_generics(&mut trait_generics, self.trait_lifetime.clone()); - - let (trait_generics, trait_ty_generics, orig_where_clause) = - trait_generics.split_for_impl(); - - quote! { - trait #proj_trait #trait_generics { - fn project<#lifetime>(&#lifetime mut self) -> #proj_ident #proj_ty_generics #orig_where_clause; - fn project_into(self) -> #proj_ident #trait_ty_generics #orig_where_clause; - } - } - } + /// Creates an implementation of the projection method. + fn make_proj_impl(&self, proj_body: &TokenStream) -> TokenStream { + let Context { proj_ident, orig_ident, lifetime, .. } = &self; - /// Creates an implementation of the projection trait. - fn make_proj_impl( - &self, - project_body: &TokenStream, - project_into_body: &TokenStream, - ) -> TokenStream { - let Context { proj_ident, proj_trait, orig_ident, lifetime, trait_lifetime, .. } = &self; let proj_generics = self.proj_generics(); - let project_into_generics = self.project_into_generics(); - let proj_ty_generics = proj_generics.split_for_impl().1; - let (impl_generics, project_into_ty_generics, _) = project_into_generics.split_for_impl(); - let (_, ty_generics, where_clause) = self.generics.split_for_impl(); + + let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); quote! { - impl #impl_generics #proj_trait #project_into_ty_generics - for ::core::pin::Pin<&#trait_lifetime mut #orig_ident #ty_generics> #where_clause - { - fn project<#lifetime>(&#lifetime mut self) -> #proj_ident #proj_ty_generics #where_clause { + impl #impl_generics #orig_ident #ty_generics #where_clause { + fn project<#lifetime>( + self: ::core::pin::Pin<&#lifetime mut Self>, + ) -> #proj_ident #proj_ty_generics { unsafe { - #project_body - } - } - fn project_into(self) -> #proj_ident #project_into_ty_generics #where_clause { - unsafe { - #project_into_body + #proj_body } } } @@ -434,7 +379,7 @@ fn ensure_not_packed(item: &ItemStruct) -> Result { // Visit structs/enums impl Context { - fn parse_struct(&mut self, item: &mut ItemStruct) -> Result { + fn parse_struct(&self, item: &mut ItemStruct) -> Result { super::validate_struct(&item.ident, &item.fields)?; let (proj_pat, proj_body, proj_fields) = match &mut item.fields { @@ -453,21 +398,17 @@ impl Context { struct #proj_ident #proj_generics #where_clause #proj_fields }; - let project_body = quote! { - let #orig_ident #proj_pat = self.as_mut().get_unchecked_mut(); - #proj_ident #proj_body - }; - let project_into_body = quote! { + let proj_body = quote! { let #orig_ident #proj_pat = self.get_unchecked_mut(); #proj_ident #proj_body }; - proj_items.extend(self.make_proj_impl(&project_body, &project_into_body)); + proj_items.extend(self.make_proj_impl(&proj_body)); Ok(proj_items) } - fn parse_enum(&mut self, item: &mut ItemEnum) -> Result { + fn parse_enum(&self, item: &mut ItemEnum) -> Result { super::validate_enum(item.brace_token, &item.variants)?; let (proj_variants, proj_arms) = self.visit_variants(item)?; @@ -484,26 +425,18 @@ impl Context { } }; - let project_body = quote! { - match self.as_mut().get_unchecked_mut() { - #(#proj_arms,)* - } - }; - let project_into_body = quote! { + let proj_body = quote! { match self.get_unchecked_mut() { - #(#proj_arms,)* + #(#proj_arms)* } }; - proj_items.extend(self.make_proj_impl(&project_body, &project_into_body)); + proj_items.extend(self.make_proj_impl(&proj_body)); Ok(proj_items) } - fn visit_variants( - &mut self, - item: &mut ItemEnum, - ) -> Result<(Vec, Vec)> { + fn visit_variants(&self, item: &mut ItemEnum) -> Result<(Vec, Vec)> { let mut proj_variants = Vec::with_capacity(item.variants.len()); let mut proj_arms = Vec::with_capacity(item.variants.len()); for Variant { attrs, fields, ident, .. } in &mut item.variants { @@ -513,7 +446,7 @@ impl Context { Fields::Unit => (TokenStream::new(), TokenStream::new(), TokenStream::new()), }; let cfg = collect_cfg(attrs); - let Self { orig_ident, proj_ident, .. } = &self; + let Self { orig_ident, proj_ident, .. } = self; proj_variants.push(quote! { #(#cfg)* #ident #proj_fields @@ -530,7 +463,7 @@ impl Context { } fn visit_named( - &mut self, + &self, FieldsNamed { named: fields, .. }: &mut FieldsNamed, ) -> Result<(TokenStream, TokenStream, TokenStream)> { let mut proj_pat = Vec::with_capacity(fields.len()); @@ -571,7 +504,7 @@ impl Context { } fn visit_unnamed( - &mut self, + &self, FieldsUnnamed { unnamed: fields, .. }: &mut FieldsUnnamed, is_struct: bool, ) -> Result<(TokenStream, TokenStream, TokenStream)> { diff --git a/pin-project-internal/src/utils.rs b/pin-project-internal/src/utils.rs index bd24f41d..2a4eab47 100644 --- a/pin-project-internal/src/utils.rs +++ b/pin-project-internal/src/utils.rs @@ -6,18 +6,12 @@ use syn::{ }; pub(crate) const DEFAULT_LIFETIME_NAME: &str = "'_pin"; -pub(crate) const TRAIT_LIFETIME_NAME: &str = "'_outer_pin"; /// Creates the ident of projected type from the ident of the original type. pub(crate) fn proj_ident(ident: &Ident) -> Ident { format_ident!("__{}Projection", ident) } -/// Creates the ident of projected trait from the ident of the original type. -pub(crate) fn proj_trait_ident(ident: &Ident) -> Ident { - format_ident!("__{}ProjectionTrait", ident) -} - /// Determine the lifetime names. Ensure it doesn't overlap with any existing lifetime names. pub(crate) fn proj_lifetime_name( lifetime_name: &mut String, diff --git a/src/lib.rs b/src/lib.rs index 569571ab..f30f5bca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ //! } //! //! impl Struct { -//! fn foo(mut self: Pin<&mut Self>) { +//! fn foo(self: Pin<&mut Self>) { //! let this = self.project(); //! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field //! let _: &mut U = this.unpinned; // Normal reference to the field diff --git a/tests/pin_project.rs b/tests/pin_project.rs index dc91e098..3dcb2704 100644 --- a/tests/pin_project.rs +++ b/tests/pin_project.rs @@ -20,7 +20,7 @@ fn test_pin_project() { let mut foo = Foo { field1: 1, field2: 2 }; let mut foo_orig = Pin::new(&mut foo); - let foo = foo_orig.project(); + let foo = foo_orig.as_mut().project(); let x: Pin<&mut i32> = foo.field1; assert_eq!(*x, 1); @@ -33,8 +33,7 @@ fn test_pin_project() { let mut foo = Foo { field1: 1, field2: 2 }; - let mut foo = Pin::new(&mut foo); - let foo = foo.project(); + let foo = Pin::new(&mut foo).project(); let __FooProjection { field1, field2 } = foo; let _: Pin<&mut i32> = field1; @@ -47,8 +46,7 @@ fn test_pin_project() { let mut bar = Bar(1, 2); - let mut bar = Pin::new(&mut bar); - let bar = bar.project(); + let bar = Pin::new(&mut bar).project(); let x: Pin<&mut i32> = bar.0; assert_eq!(*x, 1); @@ -73,7 +71,7 @@ fn test_pin_project() { let mut baz = Baz::Variant1(1, 2); let mut baz_orig = Pin::new(&mut baz); - let baz = baz_orig.project(); + let baz = baz_orig.as_mut().project(); match baz { __BazProjection::Variant1(x, y) => { @@ -94,8 +92,7 @@ fn test_pin_project() { let mut baz = Baz::Variant2 { field1: 3, field2: 4 }; - let mut baz = Pin::new(&mut baz); - let mut baz = baz.project(); + let mut baz = Pin::new(&mut baz).project(); match &mut baz { __BazProjection::Variant1(x, y) => { @@ -132,7 +129,7 @@ fn enum_project_set() { let mut bar = Bar::Variant1(25); let mut bar_orig = Pin::new(&mut bar); - let bar_proj = bar_orig.project(); + let bar_proj = bar_orig.as_mut().project(); match bar_proj { __BarProjection::Variant1(val) => { @@ -219,10 +216,9 @@ fn trait_bounds_on_type_generics() { #[test] fn overlapping_lifetime_names() { #[pin_project] - pub struct Foo<'_outer_pin, '_pin, T> { + pub struct Foo<'_pin, T> { #[pin] - field1: &'_outer_pin mut T, - field2: &'_pin mut T, + field: &'_pin mut T, } } @@ -295,30 +291,30 @@ fn lifetime_project() { impl Struct { fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> { - self.project_into().pinned + self.project().pinned } fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> { - self.project_into().pinned + self.project().pinned } } impl<'b, T, U> Struct2<'b, T, U> { fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> { - self.project_into().pinned + self.project().pinned } fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> { - self.project_into().pinned + self.project().pinned } } impl Enum { fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> { - match self.project_into() { + match self.project() { __EnumProjection::Variant { pinned, .. } => pinned, } } fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> { - match self.project_into() { + match self.project() { __EnumProjection::Variant { pinned, .. } => pinned, } } diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs index 2c0fbdc8..26dd38e5 100644 --- a/tests/pinned_drop.rs +++ b/tests/pinned_drop.rs @@ -16,7 +16,7 @@ fn safe_project() { #[pinned_drop] impl PinnedDrop for Foo<'_> { - fn drop(mut self: Pin<&mut Self>) { + fn drop(self: Pin<&mut Self>) { **self.project().was_dropped = true; } } diff --git a/tests/project.rs b/tests/project.rs index fd2b6d06..f4c9b20b 100644 --- a/tests/project.rs +++ b/tests/project.rs @@ -19,10 +19,9 @@ fn project_stmt_expr() { } let mut foo = Foo { field1: 1, field2: 2 }; - let mut foo = Pin::new(&mut foo); #[project] - let Foo { field1, field2 } = foo.project(); + let Foo { field1, field2 } = Pin::new(&mut foo).project(); let x: Pin<&mut i32> = field1; assert_eq!(*x, 1); @@ -36,10 +35,9 @@ fn project_stmt_expr() { struct Bar(#[pin] T, U); let mut bar = Bar(1, 2); - let mut bar = Pin::new(&mut bar); #[project] - let Bar(x, y) = bar.project(); + let Bar(x, y) = Pin::new(&mut bar).project(); let x: Pin<&mut i32> = x; assert_eq!(*x, 1); @@ -62,8 +60,7 @@ fn project_stmt_expr() { let mut baz = Baz::Variant1(1, 2); - let mut baz = Pin::new(&mut baz); - let mut baz = baz.project(); + let mut baz = Pin::new(&mut baz).project(); #[project] match &mut baz { diff --git a/tests/ui/project/ambiguous-let.rs b/tests/ui/project/ambiguous-let.rs index 1f83ac47..166112b7 100644 --- a/tests/ui/project/ambiguous-let.rs +++ b/tests/ui/project/ambiguous-let.rs @@ -14,10 +14,9 @@ struct Struct(T); #[project] fn foo() { let mut foo: Enum = Enum::A(true); - let mut foo = Pin::new(&mut foo); #[project] - let Struct(x) = match foo.project() { + let Struct(x) = match Pin::new(&mut foo).project() { //~^ ERROR Both initializer expression and pattern are replaceable, you need to split the initializer expression into separate let bindings to avoid ambiguity Enum::A(_) => Struct(true), Enum::B(_) => unreachable!(), diff --git a/tests/ui/project/ambiguous-let.stderr b/tests/ui/project/ambiguous-let.stderr index 3c493b0e..13c6417c 100644 --- a/tests/ui/project/ambiguous-let.stderr +++ b/tests/ui/project/ambiguous-let.stderr @@ -1,13 +1,13 @@ error: Both initializer expression and pattern are replaceable, you need to split the initializer expression into separate let bindings to avoid ambiguity - --> $DIR/ambiguous-let.rs:20:9 + --> $DIR/ambiguous-let.rs:19:9 | -20 | let Struct(x) = match foo.project() { +19 | let Struct(x) = match Pin::new(&mut foo).project() { | ^^^^^^^^^ error[E0425]: cannot find value `x` in this scope - --> $DIR/ambiguous-let.rs:25:13 + --> $DIR/ambiguous-let.rs:24:13 | -25 | assert!(x); +24 | assert!(x); | ^ not found in this scope error: aborting due to 2 previous errors diff --git a/tests/ui/project/invalid.rs b/tests/ui/project/invalid.rs index d10f27dc..c4f516e9 100644 --- a/tests/ui/project/invalid.rs +++ b/tests/ui/project/invalid.rs @@ -1,6 +1,7 @@ // compile-fail use pin_project::{pin_project, project}; +use std::pin::Pin; #[pin_project] struct A { @@ -10,9 +11,9 @@ struct A { #[project] fn foo() { - let x = A { future: 0 }; + let mut x = A { future: 0 }; #[project(foo)] //~ ERROR unexpected token - let A { future } = x.project(); + let A { future } = Pin::new(&mut x).project(); } fn main() {} diff --git a/tests/ui/project/invalid.stderr b/tests/ui/project/invalid.stderr index b84068b2..cf393b07 100644 --- a/tests/ui/project/invalid.stderr +++ b/tests/ui/project/invalid.stderr @@ -1,7 +1,7 @@ error: unexpected token - --> $DIR/invalid.rs:14:14 + --> $DIR/invalid.rs:15:14 | -14 | #[project(foo)] //~ ERROR unexpected token +15 | #[project(foo)] //~ ERROR unexpected token | ^ error: aborting due to previous error diff --git a/tests/ui/project/stmt_expr_attributes.rs b/tests/ui/project/stmt_expr_attributes.rs index 4fc6145e..f74dde5e 100644 --- a/tests/ui/project/stmt_expr_attributes.rs +++ b/tests/ui/project/stmt_expr_attributes.rs @@ -19,8 +19,7 @@ fn project_stmt_expr_nightly() { let mut baz = Baz::Variant1(1, 2); - let mut baz = Pin::new(&mut baz); - let mut baz = baz.project(); + let mut baz = Pin::new(&mut baz).project(); #[project] match &mut baz {