diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 2b223d92ff198..802d5cfbfc442 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -319,10 +319,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => expr_to_string(e), token::NtTT(ref tree) => tt_to_string(tree.clone()), - // FIXME(Centril): merge these variants. - token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e), token::NtVis(ref e) => vis_to_string(e), - token::NtForeignItem(ref e) => foreign_item_to_string(e), } } @@ -358,10 +355,6 @@ pub fn item_to_string(i: &ast::Item) -> String { to_string(|s| s.print_item(i)) } -fn assoc_item_to_string(i: &ast::AssocItem) -> String { - to_string(|s| s.print_assoc_item(i)) -} - pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String { to_string(|s| s.print_generic_params(generic_params)) } @@ -404,10 +397,6 @@ pub fn param_to_string(arg: &ast::Param) -> String { to_string(|s| s.print_param(arg, false)) } -fn foreign_item_to_string(arg: &ast::ForeignItem) -> String { - to_string(|s| s.print_foreign_item(arg)) -} - fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String { format!("{}{}", to_string(|s| s.print_visibility(vis)), s) } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index bbea066b048d2..8ed7bbf6e1276 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -669,12 +669,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); + // `Annotatable` can be converted into tokens directly, but we are packing it + // into a nonterminal as a piece of AST to make the produced token stream + // look nicer in pretty-printed form. This may be no longer necessary. let item_tok = TokenTree::token( token::Interpolated(Lrc::new(match item { Annotatable::Item(item) => token::NtItem(item), - Annotatable::TraitItem(item) => token::NtTraitItem(item), - Annotatable::ImplItem(item) => token::NtImplItem(item), - Annotatable::ForeignItem(item) => token::NtForeignItem(item), + Annotatable::TraitItem(item) + | Annotatable::ImplItem(item) + | Annotatable::ForeignItem(item) => { + token::NtItem(P(item.and_then(ast::AssocItem::into_item))) + } Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), Annotatable::Expr(expr) => token::NtExpr(expr), Annotatable::Arm(..) diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index a0b8415b3e17e..bd0b189d4fd4d 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -314,9 +314,6 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke Nonterminal::NtItem(ref item) => { prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) } - Nonterminal::NtTraitItem(ref item) | Nonterminal::NtImplItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } Nonterminal::NtIdent(ident, is_raw) => { Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into()) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d6da627054196..d9e28716c84c7 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -632,16 +632,10 @@ impl<'a> Parser<'a> { } pub fn parse_impl_item(&mut self) -> PResult<'a, Option>>> { - maybe_whole!(self, NtImplItem, |x| Some(Some(x))); self.parse_assoc_item(|_| true) } pub fn parse_trait_item(&mut self) -> PResult<'a, Option>>> { - maybe_whole!(self, NtTraitItem, |x| Some(Some(x))); - // This is somewhat dubious; We don't want to allow - // param names to be left off if there is a definition... - // - // We don't allow param names to be left off in edition 2018. self.parse_assoc_item(|t| t.span.rust_2018()) } @@ -834,8 +828,6 @@ impl<'a> Parser<'a> { /// Parses a foreign item (one in an `extern { ... }` block). pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { - maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); - Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match kind { ItemKind::Mac(a) => ForeignItemKind::Macro(a), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 19c705fa99753..62ff4f5183a70 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2441,6 +2441,13 @@ impl Item { } } +impl Item { + pub fn into_item(self) -> Item { + let Item { attrs, id, span, vis, ident, kind, tokens } = self; + Item { attrs, id, span, vis, ident, kind: kind.into_item_kind(), tokens } + } +} + /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub enum Extern { @@ -2617,6 +2624,10 @@ impl ItemKind { } } +pub trait IntoItemKind { + fn into_item_kind(self) -> ItemKind; +} + // FIXME(Centril): These definitions should be unmerged; // see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975 pub type ForeignItem = Item; @@ -2656,3 +2667,15 @@ impl AssocItemKind { } } } + +impl IntoItemKind for AssocItemKind { + fn into_item_kind(self) -> ItemKind { + match self { + AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c), + AssocItemKind::Static(a, b, c) => ItemKind::Static(a, b, c), + AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d), + AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d), + AssocItemKind::Macro(a) => ItemKind::Mac(a), + } + } +} diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 05bb07cd4b90a..b3abd4fc755e4 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -711,20 +711,7 @@ pub fn noop_visit_interpolated(nt: &mut token::Nonterminal, vis: } token::NtPath(path) => vis.visit_path(path), token::NtTT(tt) => vis.visit_tt(tt), - token::NtImplItem(item) => visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_impl_item(item).expect_one("expected visitor to produce exactly one item") - }), - token::NtTraitItem(item) => visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_trait_item(item).expect_one("expected visitor to produce exactly one item") - }), token::NtVis(visib) => vis.visit_vis(visib), - token::NtForeignItem(item) => visit_clobber(item, |item| { - // See reasoning above. - vis.flat_map_foreign_item(item) - .expect_one("expected visitor to produce exactly one item") - }), } } diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 6eeee49881579..52bf50604fb30 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -712,12 +712,6 @@ pub enum Nonterminal { NtPath(ast::Path), NtVis(ast::Visibility), NtTT(TokenTree), - // Used only for passing items to proc macro attributes (they are not - // strictly necessary for that, `Annotatable` can be converted into - // tokens directly, but doing that naively regresses pretty-printing). - NtTraitItem(P), - NtImplItem(P), - NtForeignItem(P), } // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -755,9 +749,6 @@ impl fmt::Debug for Nonterminal { NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), NtTT(..) => f.pad("NtTT(..)"), - NtImplItem(..) => f.pad("NtImplItem(..)"), - NtTraitItem(..) => f.pad("NtTraitItem(..)"), - NtForeignItem(..) => f.pad("NtForeignItem(..)"), NtVis(..) => f.pad("NtVis(..)"), NtLifetime(..) => f.pad("NtLifetime(..)"), } diff --git a/src/test/ui/proc-macro/trait-fn-args-2015.rs b/src/test/ui/proc-macro/trait-fn-args-2015.rs new file mode 100644 index 0000000000000..3a448d4b2201d --- /dev/null +++ b/src/test/ui/proc-macro/trait-fn-args-2015.rs @@ -0,0 +1,14 @@ +// Unnamed arguments in trait functions can be passed through proc macros on 2015 edition. + +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +trait Tr { + #[identity_attr] + fn method(u8); +} + +fn main() {}