From d7f4037b209fedf3e0a9d379e16acb60139a3707 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 6 Jun 2020 21:07:03 +0900 Subject: [PATCH] Allow `project_replace` argument to be used without `Replace` Also, make `project_replace` argument an alias for `Replace` so that it can be used without a value. --- examples/project_replace-expanded.rs | 2 +- examples/project_replace.rs | 2 +- pin-project-internal/src/lib.rs | 33 ++- .../src/pin_project/derive.rs | 151 ++++++++------ tests/cfg.rs | 16 +- .../tests/expand/naming-enum.expanded.rs | 2 +- tests/expand/tests/expand/naming-enum.rs | 2 +- .../tests/expand/naming-struct.expanded.rs | 2 +- tests/expand/tests/expand/naming-struct.rs | 2 +- .../expand/naming-tuple_struct.expanded.rs | 2 +- .../tests/expand/naming-tuple_struct.rs | 2 +- .../expand/project_replace-enum.expanded.rs | 2 +- .../tests/expand/project_replace-enum.rs | 2 +- .../expand/project_replace-struct.expanded.rs | 2 +- .../tests/expand/project_replace-struct.rs | 2 +- .../project_replace-tuple_struct.expanded.rs | 2 +- .../expand/project_replace-tuple_struct.rs | 2 +- tests/include/basic-safe-part.rs | 6 +- tests/lint.rs | 16 +- tests/pin_project.rs | 74 +++---- tests/project.rs | 4 +- tests/project_ref.rs | 2 +- tests/project_replace.rs | 8 +- tests/ui/pin_project/invalid.rs | 36 +++- tests/ui/pin_project/invalid.stderr | 190 +++++++++++------- .../ui/pin_project/project_replace_unsized.rs | 4 +- .../project_replace_unsized.stderr | 16 +- .../project_replace_unsized_locals.rs | 4 +- .../project_replace_unsized_locals.stderr | 8 +- tests/ui/pin_project/visibility.rs | 6 +- tests/ui/project/invalid.rs | 2 +- 31 files changed, 358 insertions(+), 246 deletions(-) diff --git a/examples/project_replace-expanded.rs b/examples/project_replace-expanded.rs index 89bb922b..c00e636c 100644 --- a/examples/project_replace-expanded.rs +++ b/examples/project_replace-expanded.rs @@ -5,7 +5,7 @@ // // use pin_project::pin_project; // -// #[pin_project(Replace)] +// #[pin_project(project_replace)] // struct Struct { // #[pin] // pinned: T, diff --git a/examples/project_replace.rs b/examples/project_replace.rs index 44826253..99cec184 100644 --- a/examples/project_replace.rs +++ b/examples/project_replace.rs @@ -4,7 +4,7 @@ use pin_project::pin_project; -#[pin_project(Replace)] +#[pin_project(project_replace)] struct Struct { #[pin] pinned: T, diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index 960de39c..dcee0bb9 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -385,14 +385,39 @@ use crate::utils::ProjKind; /// This method is opt-in, because it is only supported for [`Sized`] types, and /// because it is incompatible with the [`#[pinned_drop]`][pinned-drop] /// attribute described above. It can be enabled by using -/// `#[pin_project(Replace)]`. +/// `#[pin_project(project_replace)]`. /// /// For example: /// /// ```rust /// use pin_project::pin_project; +/// use std::{marker::PhantomData, pin::Pin}; /// -/// #[pin_project(Replace, project_replace = EnumProjOwn)] +/// #[pin_project(project_replace)] +/// struct Struct { +/// #[pin] +/// pinned_field: T, +/// unpinned_field: U, +/// } +/// +/// impl Struct { +/// fn method(self: Pin<&mut Self>, other: Self) { +/// let this = self.project_replace(other); +/// let _: U = this.unpinned_field; +/// let _: PhantomData = this.pinned_field; +/// } +/// } +/// ``` +/// +/// By passing the value to the `project_replace` argument, you can name the +/// returned type of `project_replace()`. This is necessary whenever +/// destructuring the return type of `project_replace()`, and work in exactly +/// the same way as the `project` and `project_ref` arguments. +/// +/// ```rust +/// use pin_project::pin_project; +/// +/// #[pin_project(project_replace = EnumProjOwn)] /// enum Enum { /// A { /// #[pin] @@ -410,10 +435,6 @@ use crate::utils::ProjKind; /// } /// ``` /// -/// The `project_replace` argument is necessary whenever destructuring -/// the return type of `project_replace()`, and work in exactly the same way as -/// the `project` and `project_ref` arguments. -/// /// [`PhantomData`]: core::marker::PhantomData /// [`PhantomPinned`]: core::marker::PhantomPinned /// [`Pin::as_mut`]: core::pin::Pin::as_mut diff --git a/pin-project-internal/src/pin_project/derive.rs b/pin-project-internal/src/pin_project/derive.rs index 5973e0cf..e20e35dd 100644 --- a/pin-project-internal/src/pin_project/derive.rs +++ b/pin-project-internal/src/pin_project/derive.rs @@ -1,6 +1,5 @@ use proc_macro2::{Delimiter, Group, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; -use std::fmt; use syn::{ parse::{Parse, ParseStream}, spanned::Spanned, @@ -109,16 +108,40 @@ fn validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()> { struct Args { /// `PinnedDrop` argument. pinned_drop: Option, - /// `Replace` argument. - replace: Option, /// `UnsafeUnpin` or `!Unpin` argument. unpin_impl: UnpinImpl, /// `project = ` argument. project: Option, /// `project_ref = ` argument. project_ref: Option, - /// `project_replace = ` argument. - project_replace: Option, + /// `project_replace [= ]` or `Replace` argument. + project_replace: ProjReplace, +} + +enum ProjReplace { + None, + /// `project_replace` or `Replace`. + Unnamed { + span: Span, + }, + /// `project_replace = `. + Named { + span: Span, + ident: Ident, + }, +} + +impl ProjReplace { + fn span(&self) -> Option { + match self { + ProjReplace::None => None, + ProjReplace::Named { span, .. } | ProjReplace::Unnamed { span, .. } => Some(*span), + } + } + + fn ident(&self) -> Option<&Ident> { + if let ProjReplace::Named { ident, .. } = self { Some(ident) } else { None } + } } const DUPLICATE_PIN: &str = "duplicate #[pin] attribute"; @@ -203,26 +226,15 @@ impl Parse for Args { } } - // Replace `prev` with `new`. Returns `Err` if `prev` is `Some`. - fn update_value( - prev: &mut Option, - new: T, - token: &(impl ToTokens + fmt::Display), - ) -> Result<()> { - if prev.replace(new).is_some() { - Err(error!(token, "duplicate `{}` argument", token.to_string().replace(' ', ""))) - } else { - Ok(()) - } - } - let mut pinned_drop = None; - let mut replace = None; let mut unsafe_unpin = None; let mut not_unpin = None; let mut project = None; let mut project_ref = None; - let mut project_replace = None; + + let mut replace = None; + let mut project_replace: Option<(Option, Span)> = None; + while !input.is_empty() { if input.peek(token::Bang) { let bang: token::Bang = input.parse()?; @@ -231,18 +243,21 @@ impl Parse for Args { } let unpin: kw::Unpin = input.parse()?; let span = quote!(#bang #unpin); - update_value(&mut not_unpin, span.span(), &span)?; + if not_unpin.replace(span.span()).is_some() { + return Err(error!(span, "duplicate `!Unpin` argument")); + } } else { let token = input.parse::()?; match &*token.to_string() { "PinnedDrop" => { - update_value(&mut pinned_drop, token.span(), &token)?; - } - "Replace" => { - update_value(&mut replace, token.span(), &token)?; + if pinned_drop.replace(token.span()).is_some() { + return Err(error!(token, "duplicate `PinnedDrop` argument")); + } } "UnsafeUnpin" => { - update_value(&mut unsafe_unpin, token.span(), &token)?; + if unsafe_unpin.replace(token.span()).is_some() { + return Err(error!(token, "duplicate `UnsafeUnpin` argument")); + } } "project" => { project = Some(parse_value(input, &token, project.is_some())?.0); @@ -251,8 +266,20 @@ impl Parse for Args { project_ref = Some(parse_value(input, &token, project_ref.is_some())?.0); } "project_replace" => { - project_replace = - Some(parse_value(input, &token, project_replace.is_some())?); + if input.peek(token::Eq) { + let (value, span) = + parse_value(input, &token, project_replace.is_some())?; + project_replace = Some((Some(value), span.span())); + } else if project_replace.is_some() { + return Err(error!(token, "duplicate `project_replace` argument")); + } else { + project_replace = Some((None, token.span())); + } + } + "Replace" => { + if replace.replace(token.span()).is_some() { + return Err(error!(token, "duplicate `Replace` argument")); + } } _ => return Err(error!(token, "unexpected argument: {}", token)), } @@ -264,18 +291,26 @@ impl Parse for Args { let _: token::Comma = input.parse()?; } - if let (Some((_, span)), None) = (&project_replace, replace) { - return Err(error!( - span, - "`project_replace` argument can only be used together with `Replace` argument", - )); - } - if let (Some(span), Some(_)) = (pinned_drop, replace) { - return Err(Error::new( - span, - "arguments `PinnedDrop` and `Replace` are mutually exclusive", - )); + if let Some(span) = pinned_drop { + if project_replace.is_some() { + return Err(Error::new( + span, + "arguments `PinnedDrop` and `project_replace` are mutually exclusive", + )); + } else if replace.is_some() { + return Err(Error::new( + span, + "arguments `PinnedDrop` and `Replace` are mutually exclusive", + )); + } } + let project_replace = match (project_replace, replace) { + (None, None) => ProjReplace::None, + // If both `project_replace` and `Replace` are specified, + // We always prefer `project_replace`'s span, + (Some((Some(ident), span)), _) => ProjReplace::Named { ident, span }, + (Some((_, span)), _) | (None, Some(span)) => ProjReplace::Unnamed { span }, + }; let unpin_impl = match (unsafe_unpin, not_unpin) { (None, None) => UnpinImpl::Default, (Some(span), None) => UnpinImpl::Unsafe(span), @@ -288,14 +323,7 @@ impl Parse for Args { } }; - Ok(Self { - pinned_drop, - replace, - unpin_impl, - project, - project_ref, - project_replace: project_replace.map(|(i, _)| i), - }) + Ok(Self { pinned_drop, unpin_impl, project, project_ref, project_replace }) } } @@ -357,16 +385,14 @@ struct Context<'a> { /// `PinnedDrop` argument. pinned_drop: Option, - /// `Replace` argument (requires Sized bound) - replace: Option, /// `UnsafeUnpin` or `!Unpin` argument. unpin_impl: UnpinImpl, /// `project` argument. project: bool, /// `project_ref` argument. project_ref: bool, - /// `project_replace` argument. - project_replace: bool, + /// `project_replace [= ]` or `Replace` argument. + project_replace: ProjReplace, } #[derive(Clone, Copy)] @@ -385,7 +411,7 @@ impl<'a> Context<'a> { ident: &'a Ident, generics: &'a mut Generics, ) -> Result { - let Args { pinned_drop, unpin_impl, replace, project, project_ref, project_replace } = + let Args { pinned_drop, unpin_impl, project, project_ref, project_replace } = Args::get(attrs)?; let ty_generics = generics.split_for_impl().1; @@ -409,18 +435,20 @@ impl<'a> Context<'a> { let mut where_clause = generics.clone().make_where_clause().clone(); where_clause.predicates.push(pred); + let own_ident = + project_replace.ident().cloned().unwrap_or_else(|| ProjKind::Owned.proj_ident(ident)); + Ok(Self { pinned_drop, - replace, unpin_impl, project: project.is_some(), project_ref: project_ref.is_some(), - project_replace: project_replace.is_some(), + project_replace, proj: ProjectedType { vis: determine_visibility(vis), mut_ident: project.unwrap_or_else(|| ProjKind::Mutable.proj_ident(ident)), ref_ident: project_ref.unwrap_or_else(|| ProjKind::Immutable.proj_ident(ident)), - own_ident: project_replace.unwrap_or_else(|| ProjKind::Owned.proj_ident(ident)), + own_ident, lifetime, generics: proj_generics, where_clause, @@ -436,7 +464,8 @@ impl<'a> Context<'a> { let doc_attr = quote!(#[doc(hidden)]); let doc_proj = if self.project { None } else { Some(&doc_attr) }; let doc_proj_ref = if self.project_ref { None } else { Some(&doc_attr) }; - let doc_proj_own = if self.project_replace { None } else { Some(&doc_attr) }; + let doc_proj_own = + if self.project_replace.ident().is_some() { None } else { Some(&doc_attr) }; let proj_mut = quote! { #doc_proj @@ -511,9 +540,7 @@ impl<'a> Context<'a> { #proj_ref_attrs #vis struct #proj_ref_ident #proj_generics #where_clause_ref_fields }; - if self.replace.is_some() { - // Currently, using quote_spanned here does not seem to have any effect on the - // diagnostics. + if self.project_replace.span().is_some() { proj_items.extend(quote! { #proj_own_attrs #vis struct #proj_own_ident #orig_generics #where_clause_own_fields @@ -573,9 +600,7 @@ impl<'a> Context<'a> { #proj_ref_variants } }; - if self.replace.is_some() { - // Currently, using quote_spanned here does not seem to have any effect on the - // diagnostics. + if self.project_replace.span().is_some() { proj_items.extend(quote! { #proj_own_attrs #vis enum #proj_own_ident #orig_generics #orig_where_clause { @@ -1042,7 +1067,7 @@ 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.replace.map(|span| { + let replace_impl = self.project_replace.span().map(|span| { // For interoperability with `forbid(unsafe_code)`, `unsafe` token should be // call-site span. let unsafety = token::Unsafe::default(); diff --git a/tests/cfg.rs b/tests/cfg.rs index 20b84722..41335178 100644 --- a/tests/cfg.rs +++ b/tests/cfg.rs @@ -21,7 +21,7 @@ struct Any(PhantomPinned); fn cfg() { // structs - #[pin_project(Replace)] + #[pin_project(project_replace)] struct SameName { #[cfg(target_os = "linux")] #[pin] @@ -41,7 +41,7 @@ fn cfg() { #[cfg(not(target_os = "linux"))] let _x = SameName { inner: Other }; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct DifferentName { #[cfg(target_os = "linux")] #[pin] @@ -61,7 +61,7 @@ fn cfg() { #[cfg(not(target_os = "linux"))] let _x = DifferentName { o: Other }; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct TupleStruct( #[cfg(target_os = "linux")] #[pin] @@ -83,7 +83,7 @@ fn cfg() { // enums - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Variant { #[cfg(target_os = "linux")] Inner(#[pin] Linux), @@ -110,7 +110,7 @@ fn cfg() { #[cfg(not(target_os = "linux"))] let _x = Variant::Other(Other); - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Field { SameName { #[cfg(target_os = "linux")] @@ -167,7 +167,7 @@ fn cfg() { #[test] fn cfg_attr() { - #[pin_project(Replace)] + #[pin_project(project_replace)] struct SameCfg { #[cfg(target_os = "linux")] #[cfg_attr(target_os = "linux", pin)] @@ -193,7 +193,7 @@ fn cfg_attr() { #[cfg(not(target_os = "linux"))] let _: Pin<&mut Other> = x.inner; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct DifferentCfg { #[cfg(target_os = "linux")] #[cfg_attr(target_os = "linux", pin)] @@ -233,7 +233,7 @@ fn cfg_attr() { #[test] fn cfg_attr_any_packed() { // Since `cfg(any())` can never be true, it is okay for this to pass. - #[pin_project(Replace)] + #[pin_project(project_replace)] #[cfg_attr(any(), repr(packed))] struct Struct { #[pin] diff --git a/tests/expand/tests/expand/naming-enum.expanded.rs b/tests/expand/tests/expand/naming-enum.expanded.rs index 9f58b359..56317cea 100644 --- a/tests/expand/tests/expand/naming-enum.expanded.rs +++ b/tests/expand/tests/expand/naming-enum.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -# [ pin ( __private ( Replace , project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] +# [ pin ( __private ( project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/naming-enum.rs b/tests/expand/tests/expand/naming-enum.rs index 92270f9b..dd513e6c 100644 --- a/tests/expand/tests/expand/naming-enum.rs +++ b/tests/expand/tests/expand/naming-enum.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(Replace, project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] +#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/naming-struct.expanded.rs b/tests/expand/tests/expand/naming-struct.expanded.rs index e15b313c..df11c1b7 100644 --- a/tests/expand/tests/expand/naming-struct.expanded.rs +++ b/tests/expand/tests/expand/naming-struct.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -# [ pin ( __private ( Replace , project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] +# [ pin ( __private ( project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] struct Struct { #[pin] pinned: T, diff --git a/tests/expand/tests/expand/naming-struct.rs b/tests/expand/tests/expand/naming-struct.rs index 043cc4ff..c229ba4e 100644 --- a/tests/expand/tests/expand/naming-struct.rs +++ b/tests/expand/tests/expand/naming-struct.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(Replace, project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] +#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] struct Struct { #[pin] pinned: T, diff --git a/tests/expand/tests/expand/naming-tuple_struct.expanded.rs b/tests/expand/tests/expand/naming-tuple_struct.expanded.rs index bf9477d0..3d38ad70 100644 --- a/tests/expand/tests/expand/naming-tuple_struct.expanded.rs +++ b/tests/expand/tests/expand/naming-tuple_struct.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -# [ pin ( __private ( Replace , project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] +# [ pin ( __private ( project = Proj , project_ref = ProjRef , project_replace = ProjOwn ) ) ] struct TupleStruct(#[pin] T, U); #[allow(dead_code)] #[allow(single_use_lifetimes)] diff --git a/tests/expand/tests/expand/naming-tuple_struct.rs b/tests/expand/tests/expand/naming-tuple_struct.rs index 5fdffdf9..0d95cb00 100644 --- a/tests/expand/tests/expand/naming-tuple_struct.rs +++ b/tests/expand/tests/expand/naming-tuple_struct.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(Replace, project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] +#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] struct TupleStruct(#[pin] T, U); fn main() {} diff --git a/tests/expand/tests/expand/project_replace-enum.expanded.rs b/tests/expand/tests/expand/project_replace-enum.expanded.rs index 5ce1c398..d3ccbf56 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(Replace))] +#[pin(__private(project_replace))] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/project_replace-enum.rs b/tests/expand/tests/expand/project_replace-enum.rs index c91c037e..cb314ecb 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(Replace)] +#[pin_project(project_replace)] enum Enum { Struct { #[pin] diff --git a/tests/expand/tests/expand/project_replace-struct.expanded.rs b/tests/expand/tests/expand/project_replace-struct.expanded.rs index 7e21b668..6f0c218f 100644 --- a/tests/expand/tests/expand/project_replace-struct.expanded.rs +++ b/tests/expand/tests/expand/project_replace-struct.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -#[pin(__private(Replace))] +#[pin(__private(project_replace))] struct Struct { #[pin] pinned: T, diff --git a/tests/expand/tests/expand/project_replace-struct.rs b/tests/expand/tests/expand/project_replace-struct.rs index f32846ea..5865526a 100644 --- a/tests/expand/tests/expand/project_replace-struct.rs +++ b/tests/expand/tests/expand/project_replace-struct.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(Replace)] +#[pin_project(project_replace)] struct Struct { #[pin] pinned: T, diff --git a/tests/expand/tests/expand/project_replace-tuple_struct.expanded.rs b/tests/expand/tests/expand/project_replace-tuple_struct.expanded.rs index 130102a8..1f278a8e 100644 --- a/tests/expand/tests/expand/project_replace-tuple_struct.expanded.rs +++ b/tests/expand/tests/expand/project_replace-tuple_struct.expanded.rs @@ -1,5 +1,5 @@ use pin_project::pin_project; -#[pin(__private(Replace))] +#[pin(__private(project_replace))] struct TupleStruct(#[pin] T, U); #[doc(hidden)] #[allow(dead_code)] diff --git a/tests/expand/tests/expand/project_replace-tuple_struct.rs b/tests/expand/tests/expand/project_replace-tuple_struct.rs index 52021ef6..c4d05f5f 100644 --- a/tests/expand/tests/expand/project_replace-tuple_struct.rs +++ b/tests/expand/tests/expand/project_replace-tuple_struct.rs @@ -1,6 +1,6 @@ use pin_project::pin_project; -#[pin_project(Replace)] +#[pin_project(project_replace)] struct TupleStruct(#[pin] T, U); fn main() {} diff --git a/tests/include/basic-safe-part.rs b/tests/include/basic-safe-part.rs index 90dc3a8b..3e041370 100644 --- a/tests/include/basic-safe-part.rs +++ b/tests/include/basic-safe-part.rs @@ -63,7 +63,7 @@ impl PinnedDrop for PinnedDropEnum { fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} } -#[::pin_project::pin_project(Replace)] +#[::pin_project::pin_project(project_replace)] #[derive(Debug)] pub struct ReplaceStruct { #[pin] @@ -71,11 +71,11 @@ pub struct ReplaceStruct { pub unpinned: U, } -#[::pin_project::pin_project(Replace)] +#[::pin_project::pin_project(project_replace)] #[derive(Debug)] pub struct ReplaceTupleStruct(#[pin] pub T, pub U); -#[::pin_project::pin_project(Replace)] +#[::pin_project::pin_project(project_replace)] #[derive(Debug)] pub enum ReplaceEnum { Struct { diff --git a/tests/lint.rs b/tests/lint.rs index 5f5da9b9..f1622768 100644 --- a/tests/lint.rs +++ b/tests/lint.rs @@ -51,17 +51,17 @@ pub mod forbid_unsafe { pub mod clippy { use pin_project::pin_project; - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct MutMutStruct<'a, T, U> { #[pin] pub pinned: &'a mut T, pub unpinned: &'a mut U, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct MutMutTupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U); - #[pin_project(Replace)] + #[pin_project(project_replace)] pub enum MutMutEnum<'a, T, U> { Struct { #[pin] @@ -72,7 +72,7 @@ pub mod clippy { Unit, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct TypeRepetitionInBoundsStruct where Self: Sized, @@ -82,12 +82,12 @@ pub mod clippy { pub unpinned: U, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct TypeRepetitionInBoundsTupleStruct(#[pin] T, U) where Self: Sized; - #[pin_project(Replace)] + #[pin_project(project_replace)] pub enum TypeRepetitionInBoundsEnum where Self: Sized, @@ -101,14 +101,14 @@ pub mod clippy { Unit, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct UsedUnderscoreBindingStruct { #[pin] pub _pinned: T, pub _unpinned: U, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub enum UsedUnderscoreBindingEnum { Struct { #[pin] diff --git a/tests/pin_project.rs b/tests/pin_project.rs index 957af0a0..a16d8e82 100644 --- a/tests/pin_project.rs +++ b/tests/pin_project.rs @@ -53,7 +53,7 @@ fn projection() { assert_eq!(s.field1, 3); assert_eq!(s.field2, 4); - #[pin_project(Replace)] + #[pin_project(project_replace)] struct TupleStruct(#[pin] T, U); let mut s = TupleStruct(1, 2); @@ -65,7 +65,7 @@ fn projection() { let y: &mut i32 = s.1; assert_eq!(*y, 2); - #[pin_project(Replace, project = EnumProj)] + #[pin_project(project_replace, project = EnumProj)] #[derive(Eq, PartialEq, Debug)] enum Enum { Variant1(#[pin] A, B), @@ -127,7 +127,7 @@ fn projection() { #[test] fn enum_project_set() { - #[pin_project(Replace, project = EnumProj)] + #[pin_project(project_replace, project = EnumProj)] #[derive(Eq, PartialEq, Debug)] enum Enum { Variant1(#[pin] u8), @@ -175,7 +175,7 @@ fn where_clause() { #[test] fn where_clause_and_associated_type_field() { - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct1 where I: Iterator, @@ -185,7 +185,7 @@ fn where_clause_and_associated_type_field() { field2: I::Item, } - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct2 where I: Iterator, @@ -195,7 +195,7 @@ fn where_clause_and_associated_type_field() { field2: J, } - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct3 where T: 'static, @@ -207,12 +207,12 @@ fn where_clause_and_associated_type_field() { impl Static for Struct3 {} - #[pin_project(Replace)] + #[pin_project(project_replace)] struct TupleStruct(#[pin] I, I::Item) where I: Iterator; - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum where I: Iterator, @@ -224,7 +224,7 @@ fn where_clause_and_associated_type_field() { #[test] fn derive_copy() { - #[pin_project(Replace)] + #[pin_project(project_replace)] #[derive(Clone, Copy)] struct Struct { val: T, @@ -239,7 +239,7 @@ fn derive_copy() { fn move_out() { struct NotCopy; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct { val: NotCopy, } @@ -247,7 +247,7 @@ fn move_out() { let x = Struct { val: NotCopy }; let _val: NotCopy = x.val; - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { Variant(NotCopy), } @@ -261,39 +261,39 @@ fn move_out() { #[test] fn trait_bounds_on_type_generics() { - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct1<'a, T: ?Sized> { field: &'a mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct2<'a, T: ::core::fmt::Debug> { field: &'a mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct3<'a, T: core::fmt::Debug> { field: &'a mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> { field: &'a mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> { field: &'a mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> { field: &'a mut T, } let _: Struct6<'_> = Struct6 { field: &mut [0u8; 16] }; - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct7 { field: T, } @@ -302,16 +302,16 @@ fn trait_bounds_on_type_generics() { impl Static for Struct7 {} - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct8<'a, 'b: 'a> { field1: &'a u8, field2: &'b u8, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct TupleStruct<'a, T: ?Sized>(&'a mut T); - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum<'a, T: ?Sized> { Variant(&'a mut T), } @@ -319,13 +319,13 @@ fn trait_bounds_on_type_generics() { #[test] fn overlapping_lifetime_names() { - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct1<'pin, T> { #[pin] field: &'pin mut T, } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct2<'pin, 'pin_, 'pin__> { #[pin] field: &'pin &'pin_ &'pin__ (), @@ -334,7 +334,7 @@ fn overlapping_lifetime_names() { pub trait A<'a> {} #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct HRTB<'pin___, T> where for<'pin> &'pin T: Unpin, @@ -389,7 +389,7 @@ fn combine() { #[test] fn private_type_in_public_type() { - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct PublicStruct { #[pin] inner: PrivateStruct, @@ -400,21 +400,21 @@ fn private_type_in_public_type() { #[test] fn lifetime_project() { - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct1 { #[pin] pinned: T, unpinned: U, } - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct2<'a, T, U> { #[pin] pinned: &'a mut T, unpinned: U, } - #[pin_project(Replace, project = EnumProj, project_ref = EnumProjRef)] + #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)] enum Enum { Variant { #[pin] @@ -458,21 +458,21 @@ fn lifetime_project() { #[rustversion::since(1.36)] // https://github.com/rust-lang/rust/pull/61207 #[test] fn lifetime_project_elided() { - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct1 { #[pin] pinned: T, unpinned: U, } - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct2<'a, T, U> { #[pin] pinned: &'a mut T, unpinned: U, } - #[pin_project(Replace, project = EnumProj, project_ref = EnumProjRef)] + #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)] enum Enum { Variant { #[pin] @@ -516,7 +516,7 @@ fn lifetime_project_elided() { mod visibility { use pin_project::pin_project; - #[pin_project(Replace)] + #[pin_project(project_replace)] pub(crate) struct A { pub b: u8, } @@ -534,7 +534,7 @@ fn visibility() { #[test] fn trivial_bounds() { - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct NoGenerics { #[pin] field: PhantomPinned, @@ -712,7 +712,7 @@ fn dyn_type() { fn self_in_where_clause() { pub trait Trait1 {} - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct1 where Self: Trait1, @@ -726,7 +726,7 @@ fn self_in_where_clause() { type Assoc; } - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Struct2 where Self: Trait2>, @@ -752,7 +752,7 @@ fn no_infer_outlives() { type Y = Option; } - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Foo { _x: as Bar>::Y, } @@ -765,7 +765,7 @@ fn no_infer_outlives() { fn project_replace_panic() { use std::panic; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct S { #[pin] pinned: T, diff --git a/tests/project.rs b/tests/project.rs index 982acc87..deee48ad 100644 --- a/tests/project.rs +++ b/tests/project.rs @@ -242,7 +242,7 @@ fn issue_206() { #[project] #[test] fn combine() { - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { V1(#[pin] A), V2, @@ -272,7 +272,7 @@ fn combine() { #[project_replace] #[test] fn combine_compat() { - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { V1(#[pin] A), V2, diff --git a/tests/project_ref.rs b/tests/project_ref.rs index e38ef837..eabfc552 100644 --- a/tests/project_ref.rs +++ b/tests/project_ref.rs @@ -149,7 +149,7 @@ fn project_impl() { #[project_ref] #[test] fn combine() { - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { V1(#[pin] A), V2, diff --git a/tests/project_replace.rs b/tests/project_replace.rs index 9c8a5aba..d9cda816 100644 --- a/tests/project_replace.rs +++ b/tests/project_replace.rs @@ -7,7 +7,7 @@ use std::{marker::PhantomData, pin::Pin}; #[project_replace] // Nightly does not need a dummy attribute to the function. #[test] fn project_replace_stmt_expr() { - #[pin_project(Replace)] + #[pin_project(project_replace)] struct Struct { #[pin] field1: T, @@ -27,7 +27,7 @@ fn project_replace_stmt_expr() { // tuple struct - #[pin_project(Replace)] + #[pin_project(project_replace)] struct TupleStruct(#[pin] T, U); let mut s = TupleStruct(1, 2); @@ -39,7 +39,7 @@ fn project_replace_stmt_expr() { let y: i32 = y; assert_eq!(y, 2); - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { Variant1(#[pin] A, B), Variant2 { @@ -73,7 +73,7 @@ fn project_replace_stmt_expr() { #[project_replace] #[test] fn combine() { - #[pin_project(Replace)] + #[pin_project(project_replace)] enum Enum { V1(#[pin] A), V2, diff --git a/tests/ui/pin_project/invalid.rs b/tests/ui/pin_project/invalid.rs index 6293f1c6..43c40b07 100644 --- a/tests/ui/pin_project/invalid.rs +++ b/tests/ui/pin_project/invalid.rs @@ -100,6 +100,9 @@ mod pin_project_argument { #[pin_project()] // Ok struct Unexpected4(#[pin] ()); + #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,` + struct Unexpected5(#[pin] ()); + #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument struct DuplicatePinnedDrop(#[pin] ()); @@ -128,9 +131,15 @@ mod pin_project_argument { struct DuplicateProjectRef(#[pin] ()); #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument - struct DuplicateProjectReplace(#[pin] ()); + struct DuplicateProjectReplace1(#[pin] ()); + + #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument + struct DuplicateProjectReplace2(#[pin] ()); + + #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument + struct DuplicateProjectReplace3(#[pin] ()); - #[pin_project(project_replace = A)] //~ ERROR `project_replace` argument can only be used together with `Replace` argument + #[pin_project(project_replace = A)] // Ok struct ProjectReplaceWithoutReplace(#[pin] ()); #[pin_project(PinnedDrop, Replace)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive @@ -139,6 +148,18 @@ mod pin_project_argument { #[pin_project(Replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive struct PinnedDropWithReplace2(#[pin] ()); + #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + struct PinnedDropWithProjectReplace1(#[pin] ()); + + #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + struct PinnedDropWithProjectReplace2(#[pin] ()); + + #[pin_project(project_replace, Replace)] // Ok + struct ProjectReplaceWithReplace1(#[pin] ()); + + #[pin_project(project_replace = B, Replace)] // Ok + struct ProjectReplaceWithReplace2(#[pin] ()); + #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive struct UnsafeUnpinWithNotUnpin1(#[pin] ()); @@ -157,17 +178,26 @@ mod pin_project_argument { #[pin_project(project = )] //~ ERROR expected `project = `, found `project =` struct Project2(#[pin] ()); + #[pin_project(project = !)] //~ ERROR expected identifier + struct Project3(#[pin] ()); + #[pin_project(project_ref)] //~ ERROR expected `project_ref = `, found `project_ref` struct ProjectRef1(#[pin] ()); #[pin_project(project_ref = )] //~ ERROR expected `project_ref = `, found `project_ref =` struct ProjectRef2(#[pin] ()); - #[pin_project(project_replace)] //~ ERROR expected `project_replace = `, found `project_replace` + #[pin_project(project_ref = !)] //~ ERROR expected identifier + struct ProjectRef3(#[pin] ()); + + #[pin_project(project_replace)] // Ok struct ProjectReplace1(#[pin] ()); #[pin_project(project_replace = )] //~ ERROR expected `project_replace = `, found `project_replace =` struct ProjectReplace2(#[pin] ()); + + #[pin_project(project_replace = !)] //~ ERROR expected identifier + struct ProjectReplace3(#[pin] ()); } mod pin_project_attribute { diff --git a/tests/ui/pin_project/invalid.stderr b/tests/ui/pin_project/invalid.stderr index 322043d3..316fd8c2 100644 --- a/tests/ui/pin_project/invalid.stderr +++ b/tests/ui/pin_project/invalid.stderr @@ -82,211 +82,247 @@ error: expected identifier 97 | #[pin_project(,UnsafeUnpin)] //~ ERROR expected identifier | ^ +error: expected `,` + --> $DIR/invalid.rs:103:30 + | +103 | #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,` + | ^^^^^^^^^^ + error: duplicate `PinnedDrop` argument - --> $DIR/invalid.rs:103:31 + --> $DIR/invalid.rs:106:31 | -103 | #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument +106 | #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument | ^^^^^^^^^^ error: duplicate `Replace` argument - --> $DIR/invalid.rs:106:28 + --> $DIR/invalid.rs:109:28 | -106 | #[pin_project(Replace, Replace)] //~ ERROR duplicate `Replace` argument +109 | #[pin_project(Replace, Replace)] //~ ERROR duplicate `Replace` argument | ^^^^^^^ error: duplicate `UnsafeUnpin` argument - --> $DIR/invalid.rs:109:32 + --> $DIR/invalid.rs:112:32 | -109 | #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument +112 | #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument | ^^^^^^^^^^^ error: duplicate `!Unpin` argument - --> $DIR/invalid.rs:112:27 + --> $DIR/invalid.rs:115:27 | -112 | #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument +115 | #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument | ^^^^^^ error: duplicate `UnsafeUnpin` argument - --> $DIR/invalid.rs:115:44 + --> $DIR/invalid.rs:118:44 | -115 | #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument +118 | #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument | ^^^^^^^^^^^ error: duplicate `PinnedDrop` argument - --> $DIR/invalid.rs:118:44 + --> $DIR/invalid.rs:121:44 | -118 | #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument +121 | #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument | ^^^^^^^^^^ error: duplicate `project` argument - --> $DIR/invalid.rs:121:32 + --> $DIR/invalid.rs:124:32 | -121 | #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument +124 | #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument | ^^^^^^^^^^^ error: duplicate `project` argument - --> $DIR/invalid.rs:124:49 + --> $DIR/invalid.rs:127:49 | -124 | #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument +127 | #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument | ^^^^^^^^^^^ error: duplicate `project_ref` argument - --> $DIR/invalid.rs:127:36 + --> $DIR/invalid.rs:130:36 | -127 | #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument +130 | #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument | ^^^^^^^^^^^^^^^ error: duplicate `project_replace` argument - --> $DIR/invalid.rs:130:40 + --> $DIR/invalid.rs:133:40 | -130 | #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument +133 | #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument | ^^^^^^^^^^^^^^^^^^^ -error: `project_replace` argument can only be used together with `Replace` argument - --> $DIR/invalid.rs:133:19 +error: duplicate `project_replace` argument + --> $DIR/invalid.rs:136:36 | -133 | #[pin_project(project_replace = A)] //~ ERROR `project_replace` argument can only be used together with `Replace` argument - | ^^^^^^^^^^^^^^^^^^^ +136 | #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument + | ^^^^^^^^^^^^^^^^^^^ + +error: duplicate `project_replace` argument + --> $DIR/invalid.rs:139:40 + | +139 | #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument + | ^^^^^^^^^^^^^^^ error: arguments `PinnedDrop` and `Replace` are mutually exclusive - --> $DIR/invalid.rs:136:19 + --> $DIR/invalid.rs:145:19 | -136 | #[pin_project(PinnedDrop, Replace)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive +145 | #[pin_project(PinnedDrop, Replace)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive | ^^^^^^^^^^ error: arguments `PinnedDrop` and `Replace` are mutually exclusive - --> $DIR/invalid.rs:139:41 + --> $DIR/invalid.rs:148:41 | -139 | #[pin_project(Replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive +148 | #[pin_project(Replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `Replace` are mutually exclusive | ^^^^^^^^^^ +error: arguments `PinnedDrop` and `project_replace` are mutually exclusive + --> $DIR/invalid.rs:151:19 + | +151 | #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + | ^^^^^^^^^^ + +error: arguments `PinnedDrop` and `project_replace` are mutually exclusive + --> $DIR/invalid.rs:154:49 + | +154 | #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + | ^^^^^^^^^^ + error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive - --> $DIR/invalid.rs:142:19 + --> $DIR/invalid.rs:163:19 | -142 | #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive +163 | #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive | ^^^^^^^^^^^ error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive - --> $DIR/invalid.rs:145:39 + --> $DIR/invalid.rs:166:39 | -145 | #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive +166 | #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive | ^^^^^^^^^^^ error: expected `!Unpin`, found `!` - --> $DIR/invalid.rs:148:19 + --> $DIR/invalid.rs:169:19 | -148 | #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!` +169 | #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!` | ^ error: unexpected argument: Unpin - --> $DIR/invalid.rs:151:19 + --> $DIR/invalid.rs:172:19 | -151 | #[pin_project(Unpin)] //~ ERROR unexpected argument +172 | #[pin_project(Unpin)] //~ ERROR unexpected argument | ^^^^^ error: expected `project = `, found `project` - --> $DIR/invalid.rs:154:19 + --> $DIR/invalid.rs:175:19 | -154 | #[pin_project(project)] //~ ERROR expected `project = `, found `project` +175 | #[pin_project(project)] //~ ERROR expected `project = `, found `project` | ^^^^^^^ error: expected `project = `, found `project =` - --> $DIR/invalid.rs:157:19 + --> $DIR/invalid.rs:178:19 | -157 | #[pin_project(project = )] //~ ERROR expected `project = `, found `project =` +178 | #[pin_project(project = )] //~ ERROR expected `project = `, found `project =` | ^^^^^^^^^ +error: expected identifier + --> $DIR/invalid.rs:181:29 + | +181 | #[pin_project(project = !)] //~ ERROR expected identifier + | ^ + error: expected `project_ref = `, found `project_ref` - --> $DIR/invalid.rs:160:19 + --> $DIR/invalid.rs:184:19 | -160 | #[pin_project(project_ref)] //~ ERROR expected `project_ref = `, found `project_ref` +184 | #[pin_project(project_ref)] //~ ERROR expected `project_ref = `, found `project_ref` | ^^^^^^^^^^^ error: expected `project_ref = `, found `project_ref =` - --> $DIR/invalid.rs:163:19 + --> $DIR/invalid.rs:187:19 | -163 | #[pin_project(project_ref = )] //~ ERROR expected `project_ref = `, found `project_ref =` +187 | #[pin_project(project_ref = )] //~ ERROR expected `project_ref = `, found `project_ref =` | ^^^^^^^^^^^^^ -error: expected `project_replace = `, found `project_replace` - --> $DIR/invalid.rs:166:19 +error: expected identifier + --> $DIR/invalid.rs:190:33 | -166 | #[pin_project(project_replace)] //~ ERROR expected `project_replace = `, found `project_replace` - | ^^^^^^^^^^^^^^^ +190 | #[pin_project(project_ref = !)] //~ ERROR expected identifier + | ^ error: expected `project_replace = `, found `project_replace =` - --> $DIR/invalid.rs:169:19 + --> $DIR/invalid.rs:196:19 | -169 | #[pin_project(project_replace = )] //~ ERROR expected `project_replace = `, found `project_replace =` +196 | #[pin_project(project_replace = )] //~ ERROR expected `project_replace = `, found `project_replace =` | ^^^^^^^^^^^^^^^^^ +error: expected identifier + --> $DIR/invalid.rs:199:37 + | +199 | #[pin_project(project_replace = !)] //~ ERROR expected identifier + | ^ + error: duplicate #[pin_project] attribute - --> $DIR/invalid.rs:177:5 + --> $DIR/invalid.rs:207:5 | -177 | #[pin_project] //~ ERROR duplicate #[pin_project] attribute +207 | #[pin_project] //~ ERROR duplicate #[pin_project] attribute | ^^^^^^^^^^^^^^ error: #[pin_project] attribute may not be used on structs with zero fields - --> $DIR/invalid.rs:185:19 + --> $DIR/invalid.rs:215:19 | -185 | struct Struct {} //~ ERROR may not be used on structs with zero fields +215 | 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:188:23 + --> $DIR/invalid.rs:218:23 | -188 | struct TupleStruct(); //~ ERROR may not be used on structs with zero fields +218 | 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:191:12 + --> $DIR/invalid.rs:221:12 | -191 | struct UnitStruct; //~ ERROR may not be used on structs with zero fields +221 | 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:194:20 + --> $DIR/invalid.rs:224:20 | -194 | enum EnumEmpty {} //~ ERROR may not be used on enums without variants +224 | 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:198:13 + --> $DIR/invalid.rs:228:13 | -198 | V = 2, //~ ERROR may not be used on enums with discriminants +228 | 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:203:9 + --> $DIR/invalid.rs:233:9 | -203 | / Unit, //~ ERROR may not be used on enums with zero fields -204 | | Tuple(), -205 | | Struct {}, +233 | / Unit, //~ ERROR may not be used on enums with zero fields +234 | | Tuple(), +235 | | Struct {}, | |__________________^ error: #[pin_project] attribute may only be used on structs or enums - --> $DIR/invalid.rs:209:5 + --> $DIR/invalid.rs:239:5 | -209 | / union Union { -210 | | //~^ ERROR may only be used on structs or enums -211 | | f: (), -212 | | } +239 | / union Union { +240 | | //~^ ERROR may only be used on structs or enums +241 | | f: (), +242 | | } | |_____^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:220:12 + --> $DIR/invalid.rs:250:12 | -220 | #[repr(packed)] +250 | #[repr(packed)] | ^^^^^^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:224:12 + --> $DIR/invalid.rs:254:12 | -224 | #[repr(packed)] +254 | #[repr(packed)] | ^^^^^^ error: #[pin_project] attribute may not be used on #[repr(packed)] types - --> $DIR/invalid.rs:228:12 + --> $DIR/invalid.rs:258:12 | -228 | #[repr(packed)] +258 | #[repr(packed)] | ^^^^^^ diff --git a/tests/ui/pin_project/project_replace_unsized.rs b/tests/ui/pin_project/project_replace_unsized.rs index a9485d16..706a0c1d 100644 --- a/tests/ui/pin_project/project_replace_unsized.rs +++ b/tests/ui/pin_project/project_replace_unsized.rs @@ -1,11 +1,11 @@ use pin_project::pin_project; -#[pin_project(Replace)] //~ ERROR E0277 +#[pin_project(project_replace)] //~ ERROR E0277 struct Struct { x: T, } -#[pin_project(Replace)] //~ ERROR E0277 +#[pin_project(project_replace)] //~ ERROR E0277 struct TupleStruct(T); fn main() {} diff --git a/tests/ui/pin_project/project_replace_unsized.stderr b/tests/ui/pin_project/project_replace_unsized.stderr index c0500062..c3a3be7d 100644 --- a/tests/ui/pin_project/project_replace_unsized.stderr +++ b/tests/ui/pin_project/project_replace_unsized.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized.rs:3:15 | -3 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^ doesn't have a size known at compile-time +3 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 4 | struct Struct { | - this type parameter needs to be `std::marker::Sized` | @@ -26,8 +26,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized.rs:3:1 | -3 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +3 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 4 | struct Struct { | - this type parameter needs to be `std::marker::Sized` | @@ -40,8 +40,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized.rs:8:15 | -8 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^ doesn't have a size known at compile-time +8 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 9 | struct TupleStruct(T); | - this type parameter needs to be `std::marker::Sized` | @@ -54,8 +54,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized.rs:8:1 | -8 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +8 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 9 | struct TupleStruct(T); | - this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/pin_project/project_replace_unsized_locals.rs b/tests/ui/pin_project/project_replace_unsized_locals.rs index ca6f6d72..2546041f 100644 --- a/tests/ui/pin_project/project_replace_unsized_locals.rs +++ b/tests/ui/pin_project/project_replace_unsized_locals.rs @@ -2,12 +2,12 @@ use pin_project::pin_project; -#[pin_project(Replace)] //~ ERROR E0277 +#[pin_project(project_replace)] //~ ERROR E0277 struct Struct { x: T, } -#[pin_project(Replace)] //~ ERROR E0277 +#[pin_project(project_replace)] //~ ERROR E0277 struct TupleStruct(T); fn main() {} diff --git a/tests/ui/pin_project/project_replace_unsized_locals.stderr b/tests/ui/pin_project/project_replace_unsized_locals.stderr index 8ec1cbc9..16169043 100644 --- a/tests/ui/pin_project/project_replace_unsized_locals.stderr +++ b/tests/ui/pin_project/project_replace_unsized_locals.stderr @@ -26,8 +26,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized_locals.rs:5:1 | -5 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +5 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 6 | struct Struct { | - this type parameter needs to be `std::marker::Sized` | @@ -54,8 +54,8 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/project_replace_unsized_locals.rs:10:1 | -10 | #[pin_project(Replace)] //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +10 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time 11 | struct TupleStruct(T); | - this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/pin_project/visibility.rs b/tests/ui/pin_project/visibility.rs index 7dce6ab8..01c0831b 100644 --- a/tests/ui/pin_project/visibility.rs +++ b/tests/ui/pin_project/visibility.rs @@ -4,7 +4,7 @@ mod pub_ { #[pin_project] pub struct Default(()); - #[pin_project(Replace)] + #[pin_project(project_replace)] pub struct Replace(()); } pub mod pub_use { @@ -37,7 +37,7 @@ mod pub_crate { #[pin_project] pub(crate) struct Default(()); - #[pin_project(Replace)] + #[pin_project(project_replace)] pub(crate) struct Replace(()); } pub mod pub_crate_use { @@ -55,7 +55,7 @@ mod pub_renamed { #[pin_project(project = DProj, project_ref = DProjRef)] pub struct Default(()); - #[pin_project(Replace, project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] + #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] pub struct Replace(()); } pub mod pub_renamed_use { diff --git a/tests/ui/project/invalid.rs b/tests/ui/project/invalid.rs index 07e9970c..571e4509 100644 --- a/tests/ui/project/invalid.rs +++ b/tests/ui/project/invalid.rs @@ -46,7 +46,7 @@ mod argument { mod attribute { use pin_project::{pin_project, project, project_ref, project_replace}; - #[pin_project(Replace)] + #[pin_project(project_replace)] struct A(#[pin] ()); #[project]