diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b8325f7ba3987..e50c232df2d86 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -423,6 +423,10 @@ pub trait MacResult { None } + fn make_method_receiver_expr(self: Box) -> Option> { + self.make_expr() + } + /// Creates zero or more items. fn make_items(self: Box) -> Option; 1]>> { None diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 804d3c02b413d..7dbf6e113c53a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -55,14 +55,11 @@ macro_rules! ast_fragments { $($Kind:ident($AstTy:ty) { $kind_name:expr; $(one - fn $mut_visit_ast:ident; fn $visit_ast:ident; - fn $ast_to_string:path; )? $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*); - fn $ast_to_string_elt:path; )? fn $make_ast:ident; })* @@ -71,7 +68,6 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option>), - MethodReceiverExpr(Box), $($Kind($AstTy),)* } @@ -79,7 +75,6 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, - MethodReceiverExpr, $($Kind,)* } @@ -87,7 +82,6 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", - AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -96,8 +90,6 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), - AstFragmentKind::MethodReceiverExpr => - result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -120,21 +112,14 @@ macro_rules! ast_fragments { pub(crate) fn make_opt_expr(self) -> Option> { match self { AstFragment::OptExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - } - - pub(crate) fn make_method_receiver_expr(self) -> Box { - match self { - AstFragment::MethodReceiverExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + _ => panic!("AstFragment::make_opt_expr called on the wrong kind of fragment"), } } $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + _ => panic!("AstFragment::{} called on the wrong kind of fragment", stringify!($make_ast)), } })* @@ -149,8 +134,7 @@ macro_rules! ast_fragments { *opt_expr = vis.filter_map_expr(expr) } } - AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), - $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* + $($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)* } @@ -160,27 +144,11 @@ macro_rules! ast_fragments { match self { AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)), AstFragment::OptExpr(None) => {} - AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)), $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)* $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)* } V::Result::output() } - - pub(crate) fn to_string(&self) -> String { - match self { - AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr), - AstFragment::OptExpr(None) => unreachable!(), - AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr), - $($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)* - $($( - AstFragment::$Kind(ast) => { - // The closure unwraps a `P` if present, or does nothing otherwise. - elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast)) - } - )?)* - } - } } impl<'a, 'b> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a, 'b> { @@ -195,94 +163,97 @@ macro_rules! ast_fragments { ast_fragments! { Expr(Box) { "expression"; - one fn visit_expr; fn visit_expr; fn pprust::expr_to_string; + one fn visit_expr; fn make_expr; } + MethodReceiverExpr(Box) { + "expression"; + one fn visit_method_receiver_expr; + fn make_method_receiver_expr; + } Pat(Box) { "pattern"; - one fn visit_pat; fn visit_pat; fn pprust::pat_to_string; + one fn visit_pat; fn make_pat; } Ty(Box) { "type"; - one fn visit_ty; fn visit_ty; fn pprust::ty_to_string; + one fn visit_ty; fn make_ty; } Stmts(SmallVec<[ast::Stmt; 1]>) { "statement"; - many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string; + many fn flat_map_stmt; fn visit_stmt(); fn make_stmts; } Items(SmallVec<[Box; 1]>) { "item"; - many fn flat_map_item; fn visit_item(); fn pprust::item_to_string; + many fn flat_map_item; fn visit_item(); fn make_items; } TraitItems(SmallVec<[Box; 1]>) { "trait item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait); - fn pprust::assoc_item_to_string; fn make_trait_items; } ImplItems(SmallVec<[Box; 1]>) { "impl item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false }); - fn pprust::assoc_item_to_string; fn make_impl_items; } TraitImplItems(SmallVec<[Box; 1]>) { "impl item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true }); - fn pprust::assoc_item_to_string; fn make_trait_impl_items; } ForeignItems(SmallVec<[Box; 1]>) { "foreign item"; - many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string; + many fn flat_map_foreign_item; fn visit_foreign_item(); fn make_foreign_items; } Arms(SmallVec<[ast::Arm; 1]>) { "match arm"; - many fn flat_map_arm; fn visit_arm(); fn unreachable_to_string; + many fn flat_map_arm; fn visit_arm(); fn make_arms; } ExprFields(SmallVec<[ast::ExprField; 1]>) { "field expression"; - many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string; + many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields; } PatFields(SmallVec<[ast::PatField; 1]>) { "field pattern"; - many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string; + many fn flat_map_pat_field; fn visit_pat_field(); fn make_pat_fields; } GenericParams(SmallVec<[ast::GenericParam; 1]>) { "generic parameter"; - many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string; + many fn flat_map_generic_param; fn visit_generic_param(); fn make_generic_params; } Params(SmallVec<[ast::Param; 1]>) { "function parameter"; - many fn flat_map_param; fn visit_param(); fn unreachable_to_string; + many fn flat_map_param; fn visit_param(); fn make_params; } FieldDefs(SmallVec<[ast::FieldDef; 1]>) { "field"; - many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string; + many fn flat_map_field_def; fn visit_field_def(); fn make_field_defs; } Variants(SmallVec<[ast::Variant; 1]>) { - "variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string; + "variant"; + many fn flat_map_variant; fn visit_variant(); fn make_variants; } WherePredicates(SmallVec<[ast::WherePredicate; 1]>) { "where predicate"; - many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string; + many fn flat_map_where_predicate; fn visit_where_predicate(); fn make_where_predicates; } Crate(ast::Crate) { "crate"; - one fn visit_crate; fn visit_crate; fn unreachable_to_string; + one fn visit_crate; fn make_crate; } } diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index 0d60141f274ec..d7bd5329da8b3 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -32,8 +32,34 @@ pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> Str s } -pub(crate) fn unreachable_to_string(_: &T) -> String { - unreachable!() +fn fragment_to_string(fragment: &AstFragment) -> String { + match fragment { + AstFragment::OptExpr(Some(expr)) + | AstFragment::MethodReceiverExpr(expr) + | AstFragment::Expr(expr) => pprust::expr_to_string(expr), + AstFragment::Pat(ast) => pprust::pat_to_string(ast), + AstFragment::Ty(ast) => pprust::ty_to_string(ast), + AstFragment::Stmts(ast) => elems_to_string(ast, pprust::stmt_to_string), + AstFragment::Items(ast) => elems_to_string(ast, |ast| pprust::item_to_string(ast)), + AstFragment::TraitItems(ast) + | AstFragment::ImplItems(ast) + | AstFragment::TraitImplItems(ast) => { + elems_to_string(ast, |ast| pprust::assoc_item_to_string(ast)) + } + AstFragment::ForeignItems(ast) => { + elems_to_string(ast, |ast| pprust::foreign_item_to_string(ast)) + } + AstFragment::OptExpr(None) + | AstFragment::Crate(_) + | AstFragment::Arms(_) + | AstFragment::ExprFields(_) + | AstFragment::PatFields(_) + | AstFragment::GenericParams(_) + | AstFragment::Params(_) + | AstFragment::FieldDefs(_) + | AstFragment::Variants(_) + | AstFragment::WherePredicates(_) => unreachable!(), + } } pub(crate) fn update_bang_macro_stats( @@ -98,7 +124,7 @@ pub(crate) fn update_attr_macro_stats( let input = format!( "{}\n{}", pprust::attribute_to_string(attr), - fragment_kind.expect_from_annotatables(iter::once(item)).to_string(), + fragment_to_string(&fragment_kind.expect_from_annotatables(iter::once(item))), ); update_macro_stats(ecx, MacroKind::Attr, fragment_kind, span, path, &input, fragment); } @@ -129,7 +155,7 @@ pub(crate) fn update_macro_stats( // Measure the size of the output by pretty-printing it and counting // the lines and bytes. let name = Symbol::intern(&pprust::path_to_string(path)); - let output = fragment.to_string(); + let output = fragment_to_string(fragment); let num_lines = output.trim_end().split('\n').count(); let num_bytes = output.len();