diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 744de6cd..99f649e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: rust: - - '1.37' + - '1.56' - stable - beta - nightly @@ -87,7 +87,7 @@ jobs: - run: cargo build --manifest-path tests/no-std/Cargo.toml --target thumbv6m-none-eabi - run: cargo build --manifest-path tests/rust-2015/Cargo.toml --target thumbv6m-none-eabi - run: cargo minimal-versions build --workspace --all-features --ignore-private - if: matrix.rust != '1.37' + if: matrix.rust != '1.56' miri: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 3a9f3b5b..c642cb1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "pin-project" version = "1.0.12" edition = "2018" -rust-version = "1.37" +rust-version = "1.56" license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/pin-project" keywords = ["pin", "macros", "attribute"] @@ -39,7 +39,7 @@ trybuild = "=1.0.67" # For test on MSRV. once_cell = "=1.14" -serde = "=1.0.156" +serde = "1.0.159" toml = "=0.5.9" [patch.crates-io] diff --git a/README.md b/README.md index 2e9ed4d0..8a98e04d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![crates.io](https://img.shields.io/crates/v/pin-project?style=flat-square&logo=rust)](https://crates.io/crates/pin-project) [![docs.rs](https://img.shields.io/badge/docs.rs-pin--project-blue?style=flat-square&logo=docs.rs)](https://docs.rs/pin-project) [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) -[![rustc](https://img.shields.io/badge/rustc-1.37+-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) +[![rustc](https://img.shields.io/badge/rustc-1.56+-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) [![build status](https://img.shields.io/github/actions/workflow/status/taiki-e/pin-project/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/pin-project/actions) @@ -18,7 +18,7 @@ Add this to your `Cargo.toml`: pin-project = "1" ``` -*Compiler support: requires rustc 1.37+* +*Compiler support: requires rustc 1.56+* ## Examples diff --git a/pin-project-internal/Cargo.toml b/pin-project-internal/Cargo.toml index 8529e366..3dc92390 100644 --- a/pin-project-internal/Cargo.toml +++ b/pin-project-internal/Cargo.toml @@ -2,7 +2,7 @@ name = "pin-project-internal" version = "1.0.12" edition = "2018" -rust-version = "1.37" +rust-version = "1.56" license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/pin-project" keywords = ["pin", "macros", "attribute"] @@ -20,7 +20,7 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = { version = "1.0.56", features = ["full", "visit-mut"] } +syn = { version = "2.0.1", features = ["full", "visit-mut"] } [dev-dependencies] pin-project = { path = ".." } diff --git a/pin-project-internal/src/pin_project/args.rs b/pin-project-internal/src/pin_project/args.rs index d0d4f362..d242ae71 100644 --- a/pin-project-internal/src/pin_project/args.rs +++ b/pin-project-internal/src/pin_project/args.rs @@ -16,10 +16,9 @@ pub(super) fn parse_args(attrs: &[Attribute]) -> Result { impl Parse for Input { fn parse(input: ParseStream<'_>) -> Result { Ok(Self((|| { - let content = input.parenthesized().ok()?; - let private = content.parse::().ok()?; + let private = input.parse::().ok()?; if private == "__private" { - content.parenthesized().ok()?.parse::().ok() + input.parenthesized().ok()?.parse::().ok() } else { None } @@ -31,10 +30,10 @@ pub(super) fn parse_args(attrs: &[Attribute]) -> Result { bail!(attr, "duplicate #[pin_project] attribute"); } - let mut attrs = attrs.iter().filter(|attr| attr.path.is_ident(PIN)); + let mut attrs = attrs.iter().filter(|attr| attr.path().is_ident(PIN)); let prev = if let Some(attr) = attrs.next() { - (attr, syn::parse2::(attr.tokens.clone()).unwrap().0) + (attr, syn::parse2::(attr.meta.require_list()?.tokens.clone())?.0) } else { // This only fails if another macro removes `#[pin]`. bail!(TokenStream::new(), "#[pin_project] attribute has been removed"); @@ -46,7 +45,7 @@ pub(super) fn parse_args(attrs: &[Attribute]) -> Result { // has the same span as `#[pin_project]`, it is possible // that a useless error message will be generated. // So, use the span of `prev_attr` if it is not a valid attribute. - let res = syn::parse2::(attr.tokens.clone()).unwrap().0; + let res = syn::parse2::(attr.meta.require_list()?.tokens.clone())?.0; let span = match (prev_res, res) { (Some(_), _) => attr, (None, _) => prev_attr, diff --git a/pin-project-internal/src/pin_project/derive.rs b/pin-project-internal/src/pin_project/derive.rs index ea2c9968..d2b2b5e1 100644 --- a/pin-project-internal/src/pin_project/derive.rs +++ b/pin-project-internal/src/pin_project/derive.rs @@ -1,9 +1,9 @@ use proc_macro2::{Delimiter, Group, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::{ - parse_quote, token, visit_mut::VisitMut, Attribute, Data, DataEnum, DeriveInput, Error, Field, - Fields, FieldsNamed, FieldsUnnamed, Generics, Ident, Index, Lifetime, LifetimeDef, Meta, - MetaList, MetaNameValue, NestedMeta, Result, Token, Type, Variant, Visibility, WhereClause, + parse_quote, punctuated::Punctuated, token, visit_mut::VisitMut, Attribute, Data, DataEnum, + DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, Generics, Ident, Index, + Lifetime, LifetimeParam, Meta, Result, Token, Type, Variant, Visibility, WhereClause, }; use super::{ @@ -305,7 +305,7 @@ fn validate_struct(ident: &Ident, fields: &Fields) -> Result<()> { fn validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()> { if variants.is_empty() { return Err(Error::new( - brace_token.span, + brace_token.span.join(), "#[pin_project] attribute may not be used on enums without variants", )); } @@ -569,7 +569,9 @@ fn visit_fields<'a>( let mut proj_move = TokenStream::new(); let mut pinned_bindings = Vec::with_capacity(fields.len()); - for (i, Field { attrs, vis, ident, colon_token, ty }) in fields.iter().enumerate() { + for (i, Field { attrs, vis, ident, colon_token, ty, mutability: _ }) in + fields.iter().enumerate() + { let binding = ident.clone().unwrap_or_else(|| format_ident!("_{}", i)); proj_pat.extend(quote!(#binding,)); let lifetime = &cx.proj.lifetime; @@ -768,7 +770,7 @@ fn make_unpin_impl(cx: &Context<'_>) -> TokenStream { // This ensures that any unused type parameters // don't end up with `Unpin` bounds. let lifetime_fields = cx.orig.generics.lifetimes().enumerate().map( - |(i, LifetimeDef { lifetime, .. })| { + |(i, LifetimeParam { lifetime, .. })| { let field_ident = format_ident!("__lifetime{}", i); quote!(#field_ident: &#lifetime ()) }, @@ -1016,33 +1018,26 @@ fn make_proj_impl( /// - Generates a function that borrows fields without an unsafe block and /// forbidding `unaligned_references` lint. fn ensure_not_packed(orig: &OriginalType<'_>, fields: Option<&Fields>) -> Result { - for meta in orig.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) { - if let Meta::List(list) = meta { + for attr in orig.attrs { + if let Meta::List(ref list) = attr.meta { if list.path.is_ident("repr") { - for repr in list.nested.iter() { - match repr { - NestedMeta::Meta(Meta::Path(path)) - | NestedMeta::Meta(Meta::List(MetaList { path, .. })) - | NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, .. })) => { - if path.is_ident("packed") { - let msg = if fields.is_none() { - // #[repr(packed)] cannot be apply on enums and will be rejected by rustc. - // However, we should not rely on the behavior of rustc that rejects this. - // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 - "#[repr(packed)] attribute should be applied to a struct or union" - } else if let NestedMeta::Meta(Meta::NameValue(..)) = repr { - // #[repr(packed = "")] is not valid format of #[repr(packed)] and will be - // rejected by rustc. - // However, we should not rely on the behavior of rustc that rejects this. - // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 - "#[repr(packed)] attribute should not be name-value pair" - } else { - "#[pin_project] attribute may not be used on #[repr(packed)] types" - }; - bail!(repr, msg); - } - } - NestedMeta::Lit(..) => {} + for repr in list.parse_args_with(Punctuated::::parse_terminated)? { + if repr.path().is_ident("packed") { + let msg = if fields.is_none() { + // #[repr(packed)] cannot be apply on enums and will be rejected by rustc. + // However, we should not rely on the behavior of rustc that rejects this. + // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 + "#[repr(packed)] attribute should be applied to a struct or union" + } else if repr.require_name_value().is_ok() { + // #[repr(packed = "")] is not valid format of #[repr(packed)] and will be + // rejected by rustc. + // However, we should not rely on the behavior of rustc that rejects this. + // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 + "#[repr(packed)] attribute should not be name-value pair" + } else { + "#[pin_project] attribute may not be used on #[repr(packed)] types" + }; + bail!(repr, msg); } } } diff --git a/pin-project-internal/src/pinned_drop.rs b/pin-project-internal/src/pinned_drop.rs index 912989dd..d30ecbeb 100644 --- a/pin-project-internal/src/pinned_drop.rs +++ b/pin-project-internal/src/pinned_drop.rs @@ -1,16 +1,18 @@ use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; use syn::{ - parse_quote, spanned::Spanned, visit_mut::VisitMut, Error, FnArg, GenericArgument, ImplItem, - ItemImpl, Pat, PatIdent, Path, PathArguments, Result, ReturnType, Signature, Token, Type, - TypePath, TypeReference, + parse_quote, spanned::Spanned, token::Colon, visit_mut::VisitMut, Error, FnArg, + GenericArgument, Ident, ImplItem, ItemImpl, Pat, PatIdent, PatType, Path, PathArguments, + Result, ReturnType, Signature, Token, Type, TypePath, TypeReference, }; -use crate::utils::{parse_as_empty, prepend_underscore_to_self, ReplaceReceiver, SliceExt}; +use crate::utils::{ReplaceReceiver, SliceExt}; pub(crate) fn attribute(args: &TokenStream, mut input: ItemImpl) -> TokenStream { let res = (|| -> Result<()> { - parse_as_empty(args)?; + if !args.is_empty() { + bail!(args, "unexpected argument: `{}`", args) + } validate_impl(&input)?; expand_impl(&mut input); Ok(()) @@ -85,7 +87,7 @@ fn validate_impl(item: &ItemImpl) -> Result<()> { ImplItem::Type(item) => { bail!(item, "type `{}` is not a member of trait `PinnedDrop`", item.ident) } - ImplItem::Method(method) => { + ImplItem::Fn(method) => { validate_sig(&method.sig)?; if i == 0 { Ok(()) @@ -124,14 +126,15 @@ fn validate_sig(sig: &Signature) -> Result<()> { match sig.inputs.len() { 1 => {} - 0 => return Err(Error::new(sig.paren_token.span, INVALID_ARGUMENT)), + 0 => return Err(Error::new(sig.paren_token.span.join(), INVALID_ARGUMENT)), _ => bail!(sig.inputs, INVALID_ARGUMENT), } - if let Some(FnArg::Typed(arg)) = sig.receiver() { + if let Some(arg) = sig.receiver() { // (mut) self: if let Some(path) = get_ty_path(&arg.ty) { - let ty = path.segments.last().unwrap(); + let ty = + path.segments.last().expect("Type paths should always have at least one segment"); if let PathArguments::AngleBracketed(args) = &ty.arguments { // (mut) self: (::)<&mut ..> if let Some(GenericArgument::Type(Type::Reference(TypeReference { @@ -175,25 +178,16 @@ fn validate_sig(sig: &Signature) -> Result<()> { // } // fn expand_impl(item: &mut ItemImpl) { - fn get_arg_pat(arg: &mut FnArg) -> Option<&mut PatIdent> { - if let FnArg::Typed(arg) = arg { - if let Pat::Ident(ident) = &mut *arg.pat { - return Some(ident); - } - } - None - } - // `PinnedDrop` is a private trait and should not appear in docs. item.attrs.push(parse_quote!(#[doc(hidden)])); - let path = &mut item.trait_.as_mut().unwrap().1; + let path = &mut item.trait_.as_mut().expect("unexpected inherent impl").1; *path = parse_quote_spanned! { path.span() => ::pin_project::__private::PinnedDrop }; let method = - if let ImplItem::Method(method) = &mut item.items[0] { method } else { unreachable!() }; + if let ImplItem::Fn(method) = &mut item.items[0] { method } else { unreachable!() }; // `fn drop(mut self: Pin<&mut Self>)` -> `fn __drop_inner(mut __self: Pin<&mut Receiver>)` let drop_inner = { @@ -203,8 +197,20 @@ fn expand_impl(item: &mut ItemImpl) { drop_inner.block.stmts.insert(0, parse_quote!(fn #ident() {})); drop_inner.sig.ident = ident; drop_inner.sig.generics = item.generics.clone(); - let self_pat = get_arg_pat(&mut drop_inner.sig.inputs[0]).unwrap(); - prepend_underscore_to_self(&mut self_pat.ident); + let receiver = drop_inner.sig.receiver().expect("drop() should have a receiver").clone(); + let pat = Box::new(Pat::Ident(PatIdent { + attrs: Vec::new(), + by_ref: None, + mutability: receiver.mutability, + ident: Ident::new("__self", receiver.self_token.span()), + subpat: None, + })); + drop_inner.sig.inputs[0] = FnArg::Typed(PatType { + attrs: receiver.attrs, + pat, + colon_token: Colon::default(), + ty: receiver.ty, + }); let self_ty = if let Type::Path(ty) = &*item.self_ty { ty } else { unreachable!() }; let mut visitor = ReplaceReceiver(self_ty); visitor.visit_signature_mut(&mut drop_inner.sig); @@ -214,9 +220,12 @@ fn expand_impl(item: &mut ItemImpl) { // `fn drop(mut self: Pin<&mut Self>)` -> `unsafe fn drop(self: Pin<&mut Self>)` method.sig.unsafety = Some(::default()); - let self_pat = get_arg_pat(&mut method.sig.inputs[0]).unwrap(); - self_pat.mutability = None; - let self_token = &self_pat.ident; + let self_token = if let FnArg::Receiver(ref mut rec) = method.sig.inputs[0] { + rec.mutability = None; + &rec.self_token + } else { + panic!("drop() should have a receiver") + }; method.block.stmts = parse_quote! { #[allow(clippy::needless_pass_by_value)] // This lint does not warn the receiver. diff --git a/pin-project-internal/src/utils.rs b/pin-project-internal/src/utils.rs index 27373efb..3f4ec852 100644 --- a/pin-project-internal/src/utils.rs +++ b/pin-project-internal/src/utils.rs @@ -8,7 +8,7 @@ use syn::{ punctuated::Punctuated, token, visit_mut::{self, VisitMut}, - Attribute, ExprPath, ExprStruct, Generics, Ident, Item, Lifetime, LifetimeDef, Macro, PatPath, + Attribute, ExprPath, ExprStruct, Generics, Ident, Item, Lifetime, LifetimeParam, Macro, PatStruct, PatTupleStruct, Path, PathArguments, PredicateType, QSelf, Result, Token, Type, TypeParamBound, TypePath, Variant, Visibility, WherePredicate, }; @@ -42,7 +42,7 @@ pub(crate) fn determine_lifetime_name(lifetime_name: &mut String, generics: &mut struct CollectLifetimes(Vec); impl VisitMut for CollectLifetimes { - fn visit_lifetime_def_mut(&mut self, def: &mut LifetimeDef) { + fn visit_lifetime_param_mut(&mut self, def: &mut LifetimeParam) { self.0.push(def.lifetime.to_string()); } } @@ -84,7 +84,7 @@ pub(crate) fn insert_lifetime_and_bound( pub(crate) fn insert_lifetime(generics: &mut Generics, lifetime: Lifetime) { generics.lt_token.get_or_insert_with(::default); generics.gt_token.get_or_insert_with(]>::default); - generics.params.insert(0, LifetimeDef::new(lifetime).into()); + generics.params.insert(0, LifetimeParam::new(lifetime).into()); } /// Determines the visibility of the projected types and projection methods. @@ -93,24 +93,12 @@ pub(crate) fn insert_lifetime(generics: &mut Generics, lifetime: Lifetime) { /// Otherwise, returned visibility is the same as given visibility. pub(crate) fn determine_visibility(vis: &Visibility) -> Visibility { if let Visibility::Public(token) = vis { - parse_quote_spanned!(token.pub_token.span => pub(crate)) + parse_quote_spanned!(token.span => pub(crate)) } else { vis.clone() } } -/// Checks if `tokens` is an empty `TokenStream`. -/// -/// This is almost equivalent to `syn::parse2::()`, but produces -/// a better error message and does not require ownership of `tokens`. -pub(crate) fn parse_as_empty(tokens: &TokenStream) -> Result<()> { - if tokens.is_empty() { - Ok(()) - } else { - bail!(tokens, "unexpected token: `{}`", tokens) - } -} - pub(crate) fn respan(node: &T, span: Span) -> T where T: ToTokens + Parse, @@ -146,11 +134,11 @@ impl SliceExt for [Attribute] { fn position_exact(&self, ident: &str) -> Result> { self.iter() .try_fold((0, None), |(i, mut prev), attr| { - if attr.path.is_ident(ident) { + if attr.path().is_ident(ident) { if prev.replace(i).is_some() { bail!(attr, "duplicate #[{}] attribute", ident); } - parse_as_empty(&attr.tokens)?; + attr.meta.require_path_only()?; } Ok((i + 1, prev)) }) @@ -158,7 +146,7 @@ impl SliceExt for [Attribute] { } fn find(&self, ident: &str) -> Option<&Attribute> { - self.iter().position(|attr| attr.path.is_ident(ident)).map(|i| &self[i]) + self.iter().position(|attr| attr.path().is_ident(ident)).map(|i| &self[i]) } } @@ -335,13 +323,6 @@ impl VisitMut for ReplaceReceiver<'_> { visit_mut::visit_expr_struct_mut(self, expr); } - fn visit_pat_path_mut(&mut self, pat: &mut PatPath) { - if pat.qself.is_none() { - self.self_to_qself(&mut pat.qself, &mut pat.path); - } - visit_mut::visit_pat_path_mut(self, pat); - } - fn visit_pat_struct_mut(&mut self, pat: &mut PatStruct) { self.self_to_expr_path(&mut pat.path); visit_mut::visit_pat_struct_mut(self, pat); diff --git a/src/lib.rs b/src/lib.rs index f81bc008..9419e288 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ Add this to your `Cargo.toml`: pin-project = "1" ``` -*Compiler support: requires rustc 1.37+* +*Compiler support: requires rustc 1.56+* ## Examples diff --git a/tests/auxiliary/macro/Cargo.toml b/tests/auxiliary/macro/Cargo.toml index 94160b95..2fa3155d 100644 --- a/tests/auxiliary/macro/Cargo.toml +++ b/tests/auxiliary/macro/Cargo.toml @@ -12,4 +12,4 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = { version = "1", features = ["full"] } +syn = { version = "2", features = ["full"] } diff --git a/tests/auxiliary/macro/lib.rs b/tests/auxiliary/macro/lib.rs index e81a7236..19deb025 100644 --- a/tests/auxiliary/macro/lib.rs +++ b/tests/auxiliary/macro/lib.rs @@ -4,7 +4,7 @@ use proc_macro::TokenStream; use quote::{format_ident, quote, ToTokens}; -use syn::{parse_quote, Field, Fields, ItemStruct, Token, Visibility}; +use syn::{parse_quote, Field, FieldMutability, Fields, ItemStruct, Token, Visibility}; fn tokens2(tokens: TokenStream) -> proc_macro2::TokenStream { tokens.into() @@ -52,6 +52,7 @@ pub fn add_pinned_field(_: TokenStream, input: TokenStream) -> TokenStream { ident: Some(format_ident!("__field")), colon_token: Some(::default()), ty: parse_quote!(::std::marker::PhantomPinned), + mutability: FieldMutability::None, }); item.into_token_stream().into() @@ -72,7 +73,7 @@ pub fn remove_attr(args: TokenStream, input: TokenStream) -> TokenStream { while item .attrs .iter() - .position(|a| a.path.is_ident("pin")) + .position(|a| a.path().is_ident("pin")) .map(|i| item.attrs.remove(i)) .is_some() {} diff --git a/tests/ui/pin_project/add-attr-to-struct.rs b/tests/ui/pin_project/add-attr-to-struct.rs index 045e7966..32253d70 100644 --- a/tests/ui/pin_project/add-attr-to-struct.rs +++ b/tests/ui/pin_project/add-attr-to-struct.rs @@ -4,7 +4,7 @@ use auxiliary_macro::add_pin_attr; use pin_project::pin_project; #[pin_project] -#[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute +#[add_pin_attr(struct)] //~ ERROR expected attribute arguments in parentheses struct Foo { #[pin] f: PhantomPinned, diff --git a/tests/ui/pin_project/add-attr-to-struct.stderr b/tests/ui/pin_project/add-attr-to-struct.stderr index 6fb88e80..bb76c62d 100644 --- a/tests/ui/pin_project/add-attr-to-struct.stderr +++ b/tests/ui/pin_project/add-attr-to-struct.stderr @@ -1,7 +1,7 @@ -error: duplicate #[pin] attribute +error: expected attribute arguments in parentheses: `pin(...)` --> tests/ui/pin_project/add-attr-to-struct.rs:7:1 | -7 | #[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute +7 | #[add_pin_attr(struct)] //~ ERROR expected attribute arguments in parentheses | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/invalid.rs b/tests/ui/pin_project/invalid.rs index d39a1fd4..a850c571 100644 --- a/tests/ui/pin_project/invalid.rs +++ b/tests/ui/pin_project/invalid.rs @@ -3,22 +3,22 @@ mod pin_argument { #[pin_project] struct Struct { - #[pin()] //~ ERROR unexpected token + #[pin()] //~ ERROR unexpected token in attribute f: (), } #[pin_project] - struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token + struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token in attribute #[pin_project] enum EnumTuple { - V(#[pin(foo)] ()), //~ ERROR unexpected token + V(#[pin(foo)] ()), //~ ERROR unexpected token in attribute } #[pin_project] enum EnumStruct { V { - #[pin(foo)] //~ ERROR unexpected token + #[pin(foo)] //~ ERROR unexpected token in attribute f: (), }, } diff --git a/tests/ui/pin_project/invalid.stderr b/tests/ui/pin_project/invalid.stderr index c43d363d..ec5205f5 100644 --- a/tests/ui/pin_project/invalid.stderr +++ b/tests/ui/pin_project/invalid.stderr @@ -1,26 +1,26 @@ -error: unexpected token: `()` +error: unexpected token in attribute --> tests/ui/pin_project/invalid.rs:6:14 | -6 | #[pin()] //~ ERROR unexpected token - | ^^ +6 | #[pin()] //~ ERROR unexpected token in attribute + | ^ -error: unexpected token: `(foo)` +error: unexpected token in attribute --> tests/ui/pin_project/invalid.rs:11:29 | -11 | struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token - | ^^^^^ +11 | struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token in attribute + | ^ -error: unexpected token: `(foo)` +error: unexpected token in attribute --> tests/ui/pin_project/invalid.rs:15:16 | -15 | V(#[pin(foo)] ()), //~ ERROR unexpected token - | ^^^^^ +15 | V(#[pin(foo)] ()), //~ ERROR unexpected token in attribute + | ^ -error: unexpected token: `(foo)` +error: unexpected token in attribute --> tests/ui/pin_project/invalid.rs:21:18 | -21 | #[pin(foo)] //~ ERROR unexpected token - | ^^^^^ +21 | #[pin(foo)] //~ ERROR unexpected token in attribute + | ^ error: duplicate #[pin] attribute --> tests/ui/pin_project/invalid.rs:33:9 diff --git a/tests/ui/pinned_drop/invalid.rs b/tests/ui/pinned_drop/invalid.rs index fdadf8a5..b2c25265 100644 --- a/tests/ui/pinned_drop/invalid.rs +++ b/tests/ui/pinned_drop/invalid.rs @@ -6,7 +6,7 @@ mod argument { #[pin_project(PinnedDrop)] struct UnexpectedArg1(()); - #[pinned_drop(foo)] //~ ERROR unexpected token + #[pinned_drop(foo)] //~ ERROR unexpected argument impl PinnedDrop for UnexpectedArg1 { fn drop(self: Pin<&mut Self>) {} } diff --git a/tests/ui/pinned_drop/invalid.stderr b/tests/ui/pinned_drop/invalid.stderr index d509964b..264def08 100644 --- a/tests/ui/pinned_drop/invalid.stderr +++ b/tests/ui/pinned_drop/invalid.stderr @@ -1,7 +1,7 @@ -error: unexpected token: `foo` +error: unexpected argument: `foo` --> tests/ui/pinned_drop/invalid.rs:9:19 | -9 | #[pinned_drop(foo)] //~ ERROR unexpected token +9 | #[pinned_drop(foo)] //~ ERROR unexpected argument | ^^^ error: duplicate #[pinned_drop] attribute