From 8d5eb6badbdd29492ad5820ce4d454130d041c4b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 6 Jul 2025 00:36:02 -0700 Subject: [PATCH 1/4] mbe: Simplify compile_declarative_macro by factoring out some variables --- compiler/rustc_expand/src/mbe/macro_rules.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 52cdcc5c747e9..75407154a45e7 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -373,17 +373,10 @@ pub fn compile_declarative_macro( node_id: NodeId, edition: Edition, ) -> (SyntaxExtension, usize) { + let is_local = node_id != DUMMY_NODE_ID; let mk_syn_ext = |expander| { - SyntaxExtension::new( - sess, - SyntaxExtensionKind::LegacyBang(expander), - span, - Vec::new(), - edition, - ident.name, - attrs, - node_id != DUMMY_NODE_ID, - ) + let kind = SyntaxExtensionKind::LegacyBang(expander); + SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local) }; let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0); @@ -454,7 +447,7 @@ pub fn compile_declarative_macro( } // Return the number of rules for unused rule linting, if this is a local macro. - let nrules = if node_id != DUMMY_NODE_ID { rules.len() } else { 0 }; + let nrules = if is_local { rules.len() } else { 0 }; let expander = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules }); From 87cd178159205edf5245fd42b55a4620dadcc8d1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 6 Jul 2025 14:40:37 -0700 Subject: [PATCH 2/4] mbe: Factor out a helper to check an LHS This currently gets called only once, but will get called multiple times when handling attributes. --- compiler/rustc_expand/src/mbe/macro_rules.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 75407154a45e7..f310e7264ac1c 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -397,8 +397,7 @@ pub fn compile_declarative_macro( let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition); // We don't handle errors here, the driver will abort after parsing/expansion. We can // report every error in every macro this way. - check_emission(check_lhs_nt_follows(sess, node_id, &lhs_tt)); - check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(&lhs_tt))); + check_emission(check_lhs(sess, node_id, &lhs_tt)); if let Err(e) = p.expect(exp!(FatArrow)) { return dummy_syn_ext(e.emit()); } @@ -454,6 +453,12 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), nrules) } +fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> { + let e1 = check_lhs_nt_follows(sess, node_id, lhs); + let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs)); + e1.and(e2) +} + fn check_lhs_nt_follows( sess: &Session, node_id: NodeId, From 493cdf226922495b861c6fd6f0c4ddfcedaa99d9 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 6 Jul 2025 16:22:25 -0700 Subject: [PATCH 3/4] mbe: Factor out a helper to check for unexpected EOF in definition Will get called additional times when expanding parsing to cover attributes --- compiler/rustc_expand/src/mbe/macro_rules.rs | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index f310e7264ac1c..26b37caac4807 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -401,13 +401,7 @@ pub fn compile_declarative_macro( if let Err(e) = p.expect(exp!(FatArrow)) { return dummy_syn_ext(e.emit()); } - if p.token == token::Eof { - let err_sp = p.token.span.shrink_to_hi(); - let guar = sess - .dcx() - .struct_span_err(err_sp, "macro definition ended unexpectedly") - .with_span_label(err_sp, "expected right-hand side of macro rule") - .emit(); + if let Some(guar) = check_no_eof(sess, &p, "expected right-hand side of macro rule") { return dummy_syn_ext(guar); } let rhs_tt = p.parse_token_tree(); @@ -453,6 +447,19 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), nrules) } +fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option { + if p.token == token::Eof { + let err_sp = p.token.span.shrink_to_hi(); + let guar = sess + .dcx() + .struct_span_err(err_sp, "macro definition ended unexpectedly") + .with_span_label(err_sp, msg) + .emit(); + return Some(guar); + } + None +} + fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> { let e1 = check_lhs_nt_follows(sess, node_id, lhs); let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs)); From ef0465a7eb49252265701454cec222575a425b77 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 6 Jul 2025 20:47:06 -0700 Subject: [PATCH 4/4] mbe: Clarify comments about error handling in `compile_declarative_macro` --- compiler/rustc_expand/src/mbe/macro_rules.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 26b37caac4807..89547088f501f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -386,7 +386,8 @@ pub fn compile_declarative_macro( let body = macro_def.body.tokens.clone(); let mut p = Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS); - // Don't abort iteration early, so that multiple errors can be reported. + // Don't abort iteration early, so that multiple errors can be reported. We only abort early on + // parse failures we can't recover from. let mut guar = None; let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err()); @@ -395,8 +396,6 @@ pub fn compile_declarative_macro( while p.token != token::Eof { let lhs_tt = p.parse_token_tree(); let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition); - // We don't handle errors here, the driver will abort after parsing/expansion. We can - // report every error in every macro this way. check_emission(check_lhs(sess, node_id, &lhs_tt)); if let Err(e) = p.expect(exp!(FatArrow)) { return dummy_syn_ext(e.emit());