From c13cfc627efadd44664104ed5cbafb776273a745 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 15 Apr 2026 12:10:16 +0000 Subject: [PATCH 1/5] move `AstFragment::to_string` out of `ast_fragments!` --- compiler/rustc_expand/src/expand.rs | 82 +++++++++++++++++------------ compiler/rustc_expand/src/stats.rs | 4 -- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 804d3c02b413d..861af0fd74203 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -57,12 +57,10 @@ macro_rules! ast_fragments { $(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; })* @@ -166,21 +164,6 @@ macro_rules! ast_fragments { } 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,98 +178,127 @@ 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 visit_expr; fn make_expr; } Pat(Box) { "pattern"; - one fn visit_pat; fn visit_pat; fn pprust::pat_to_string; + one fn visit_pat; 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 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 visit_crate; fn make_crate; } } +impl AstFragment { + pub(crate) fn to_string(&self) -> String { + match self { + 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 enum SupportsMacroExpansion { No, Yes { supports_inner_attrs: bool }, diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index 0d60141f274ec..ef1668e4af25c 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -32,10 +32,6 @@ 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!() -} - pub(crate) fn update_bang_macro_stats( ecx: &mut ExtCtxt<'_>, fragment_kind: AstFragmentKind, From 712d30f79f37d3f6520e8f0521580ff871610b81 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 15 Apr 2026 12:21:14 +0000 Subject: [PATCH 2/5] merge `$mut_visit_ast` and `$visit_ast` --- compiler/rustc_expand/src/expand.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 861af0fd74203..762f293c1e443 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -55,7 +55,6 @@ macro_rules! ast_fragments { $($Kind:ident($AstTy:ty) { $kind_name:expr; $(one - fn $mut_visit_ast:ident; fn $visit_ast:ident; )? $(many @@ -148,7 +147,7 @@ macro_rules! ast_fragments { } } 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)*)),)?)* } @@ -178,17 +177,17 @@ macro_rules! ast_fragments { ast_fragments! { Expr(Box) { "expression"; - one fn visit_expr; fn visit_expr; + one fn visit_expr; fn make_expr; } Pat(Box) { "pattern"; - one fn visit_pat; fn visit_pat; + one fn visit_pat; fn make_pat; } Ty(Box) { "type"; - one fn visit_ty; fn visit_ty; + one fn visit_ty; fn make_ty; } Stmts(SmallVec<[ast::Stmt; 1]>) { @@ -262,7 +261,7 @@ ast_fragments! { } Crate(ast::Crate) { "crate"; - one fn visit_crate; fn visit_crate; + one fn visit_crate; fn make_crate; } } From 210f03a1cfb1a44a48df67ce070576e9098ae876 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 19 Apr 2026 20:53:05 +0000 Subject: [PATCH 3/5] smaller tweaks --- compiler/rustc_expand/src/expand.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 762f293c1e443..baabc6ebd75fc 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -117,21 +117,21 @@ 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"), + _ => panic!("AstFragment::make_opt_expr 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_method_receiver_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)), } })* @@ -251,7 +251,8 @@ ast_fragments! { fn make_field_defs; } Variants(SmallVec<[ast::Variant; 1]>) { - "variant"; many fn flat_map_variant; fn visit_variant(); + "variant"; + many fn flat_map_variant; fn visit_variant(); fn make_variants; } WherePredicates(SmallVec<[ast::WherePredicate; 1]>) { From 5ad560f7ec96bd42f003abe9842abe6e5643817e Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 28 Apr 2026 10:26:46 +0000 Subject: [PATCH 4/5] remove `MethodReceiverExpr` special-casing --- compiler/rustc_expand/src/base.rs | 4 ++++ compiler/rustc_expand/src/expand.rs | 19 +++++-------------- 2 files changed, 9 insertions(+), 14 deletions(-) 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 baabc6ebd75fc..53bb7c9c03857 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -68,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),)* } @@ -76,7 +75,6 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, - MethodReceiverExpr, $($Kind,)* } @@ -84,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,)* } } @@ -93,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),)* } } @@ -121,13 +116,6 @@ macro_rules! ast_fragments { } } - pub(crate) fn make_method_receiver_expr(self) -> Box { - match self { - AstFragment::MethodReceiverExpr(expr) => expr, - _ => panic!("AstFragment::make_method_receiver_expr called on the wrong kind of fragment"), - } - } - $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, @@ -146,7 +134,6 @@ macro_rules! ast_fragments { *opt_expr = vis.filter_map_expr(expr) } } - AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)* @@ -157,7 +144,6 @@ 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)*),)?)* } @@ -180,6 +166,11 @@ ast_fragments! { 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; From 72a59e73d87f7219ad4a865f0ed28e3e55060b22 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 29 Apr 2026 11:17:05 +0000 Subject: [PATCH 5/5] move fragment printing code --- compiler/rustc_expand/src/expand.rs | 32 --------------------------- compiler/rustc_expand/src/stats.rs | 34 +++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 53bb7c9c03857..7dbf6e113c53a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -258,38 +258,6 @@ ast_fragments! { } } -impl AstFragment { - pub(crate) fn to_string(&self) -> String { - match self { - 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 enum SupportsMacroExpansion { No, Yes { supports_inner_attrs: bool }, diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index ef1668e4af25c..d7bd5329da8b3 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -32,6 +32,36 @@ pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> Str s } +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( ecx: &mut ExtCtxt<'_>, fragment_kind: AstFragmentKind, @@ -94,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); } @@ -125,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();