@@ -109,6 +109,7 @@ use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
109109use rustc_ast:: { DUMMY_NODE_ID , NodeId } ;
110110use rustc_data_structures:: fx:: FxHashMap ;
111111use rustc_errors:: DecorateDiagCompat ;
112+ use rustc_parse:: parser:: ForceCollect ;
112113use rustc_session:: lint:: builtin:: META_VARIABLE_MISUSE ;
113114use rustc_session:: parse:: ParseSess ;
114115use rustc_span:: { ErrorGuaranteed , MacroRulesNormalizedIdent , Span , kw} ;
@@ -193,20 +194,23 @@ struct MacroState<'a> {
193194/// - `psess` is used to emit diagnostics and lints
194195/// - `node_id` is used to emit lints
195196/// - `args`, `lhs`, and `rhs` represent the rule
197+ /// - `collect` is set to the token collection mode needed for the macro (recursive if any metavar exprs)
196198pub ( super ) fn check_meta_variables (
197199 psess : & ParseSess ,
198200 node_id : NodeId ,
199201 args : Option < & TokenTree > ,
200202 lhs : & TokenTree ,
201203 rhs : & TokenTree ,
204+ collect : & mut ForceCollect ,
202205) -> Result < ( ) , ErrorGuaranteed > {
203206 let mut guar = None ;
204207 let mut binders = Binders :: default ( ) ;
208+ let ops = & Stack :: Empty ;
205209 if let Some ( args) = args {
206- check_binders ( psess, node_id, args, & Stack :: Empty , & mut binders, & Stack :: Empty , & mut guar) ;
210+ check_binders ( psess, node_id, args, & Stack :: Empty , & mut binders, ops , collect , & mut guar) ;
207211 }
208- check_binders ( psess, node_id, lhs, & Stack :: Empty , & mut binders, & Stack :: Empty , & mut guar) ;
209- check_occurrences ( psess, node_id, rhs, & Stack :: Empty , & binders, & Stack :: Empty , & mut guar) ;
212+ check_binders ( psess, node_id, lhs, & Stack :: Empty , & mut binders, ops , collect , & mut guar) ;
213+ check_occurrences ( psess, node_id, rhs, & Stack :: Empty , & binders, ops , collect , & mut guar) ;
210214 guar. map_or ( Ok ( ( ) ) , Err )
211215}
212216
@@ -220,6 +224,7 @@ pub(super) fn check_meta_variables(
220224/// - `macros` is the stack of possible outer macros
221225/// - `binders` contains the binders of the LHS
222226/// - `ops` is the stack of Kleene operators from the LHS
227+ /// - `collect` is updated to recursive if we encounter any metadata expressions
223228/// - `guar` is set in case of errors
224229fn check_binders (
225230 psess : & ParseSess ,
@@ -228,6 +233,7 @@ fn check_binders(
228233 macros : & Stack < ' _ , MacroState < ' _ > > ,
229234 binders : & mut Binders ,
230235 ops : & Stack < ' _ , KleeneToken > ,
236+ collect : & mut ForceCollect ,
231237 guar : & mut Option < ErrorGuaranteed > ,
232238) {
233239 match * lhs {
@@ -255,7 +261,7 @@ fn check_binders(
255261 binders. insert ( name, BinderInfo { span, ops : ops. into ( ) } ) ;
256262 } else {
257263 // 3. The meta-variable is bound: This is an occurrence.
258- check_occurrences ( psess, node_id, lhs, macros, binders, ops, guar) ;
264+ check_occurrences ( psess, node_id, lhs, macros, binders, ops, collect , guar) ;
259265 }
260266 }
261267 // Similarly, this can only happen when checking a toplevel macro.
@@ -280,13 +286,13 @@ fn check_binders(
280286 TokenTree :: MetaVarExpr ( ..) => { }
281287 TokenTree :: Delimited ( .., ref del) => {
282288 for tt in & del. tts {
283- check_binders ( psess, node_id, tt, macros, binders, ops, guar) ;
289+ check_binders ( psess, node_id, tt, macros, binders, ops, collect , guar) ;
284290 }
285291 }
286292 TokenTree :: Sequence ( _, ref seq) => {
287293 let ops = ops. push ( seq. kleene ) ;
288294 for tt in & seq. tts {
289- check_binders ( psess, node_id, tt, macros, binders, & ops, guar) ;
295+ check_binders ( psess, node_id, tt, macros, binders, & ops, collect , guar) ;
290296 }
291297 }
292298 }
@@ -316,6 +322,7 @@ fn get_binder_info<'a>(
316322/// - `macros` is the stack of possible outer macros
317323/// - `binders` contains the binders of the associated LHS
318324/// - `ops` is the stack of Kleene operators from the RHS
325+ /// - `collect` is updated to recursive if we encounter any metadata expressions
319326/// - `guar` is set in case of errors
320327fn check_occurrences (
321328 psess : & ParseSess ,
@@ -324,6 +331,7 @@ fn check_occurrences(
324331 macros : & Stack < ' _ , MacroState < ' _ > > ,
325332 binders : & Binders ,
326333 ops : & Stack < ' _ , KleeneToken > ,
334+ collect : & mut ForceCollect ,
327335 guar : & mut Option < ErrorGuaranteed > ,
328336) {
329337 match * rhs {
@@ -336,17 +344,21 @@ fn check_occurrences(
336344 check_ops_is_prefix ( psess, node_id, macros, binders, ops, span, name) ;
337345 }
338346 TokenTree :: MetaVarExpr ( dl, ref mve) => {
347+ // Require recursive token collection if we have any metadata expressions
348+ * collect = ForceCollect :: Recursive ;
339349 mve. for_each_metavar ( ( ) , |_, ident| {
340350 let name = MacroRulesNormalizedIdent :: new ( * ident) ;
341351 check_ops_is_prefix ( psess, node_id, macros, binders, ops, dl. entire ( ) , name) ;
342352 } ) ;
343353 }
344354 TokenTree :: Delimited ( .., ref del) => {
345- check_nested_occurrences ( psess, node_id, & del. tts , macros, binders, ops, guar) ;
355+ check_nested_occurrences ( psess, node_id, & del. tts , macros, binders, ops, collect , guar) ;
346356 }
347357 TokenTree :: Sequence ( _, ref seq) => {
348358 let ops = ops. push ( seq. kleene ) ;
349- check_nested_occurrences ( psess, node_id, & seq. tts , macros, binders, & ops, guar) ;
359+ check_nested_occurrences (
360+ psess, node_id, & seq. tts , macros, binders, & ops, collect, guar,
361+ ) ;
350362 }
351363 }
352364}
@@ -381,6 +393,7 @@ enum NestedMacroState {
381393/// - `macros` is the stack of possible outer macros
382394/// - `binders` contains the binders of the associated LHS
383395/// - `ops` is the stack of Kleene operators from the RHS
396+ /// - `collect` is updated to recursive if we encounter metadata expressions or nested macros
384397/// - `guar` is set in case of errors
385398fn check_nested_occurrences (
386399 psess : & ParseSess ,
@@ -389,6 +402,7 @@ fn check_nested_occurrences(
389402 macros : & Stack < ' _ , MacroState < ' _ > > ,
390403 binders : & Binders ,
391404 ops : & Stack < ' _ , KleeneToken > ,
405+ collect : & mut ForceCollect ,
392406 guar : & mut Option < ErrorGuaranteed > ,
393407) {
394408 let mut state = NestedMacroState :: Empty ;
@@ -421,16 +435,26 @@ fn check_nested_occurrences(
421435 ( NestedMacroState :: MacroRulesBang , & TokenTree :: MetaVar ( ..) ) => {
422436 state = NestedMacroState :: MacroRulesBangName ;
423437 // We check that the meta-variable is correctly used.
424- check_occurrences ( psess, node_id, tt, macros, binders, ops, guar) ;
438+ check_occurrences ( psess, node_id, tt, macros, binders, ops, collect , guar) ;
425439 }
426440 ( NestedMacroState :: MacroRulesBangName , TokenTree :: Delimited ( .., del) )
427441 | ( NestedMacroState :: MacroName , TokenTree :: Delimited ( .., del) )
428442 if del. delim == Delimiter :: Brace =>
429443 {
444+ // Conservatively assume that we might need recursive tokens, since our parsing in
445+ // the face of nested macro definitions is fuzzy.
446+ * collect = ForceCollect :: Recursive ;
430447 let macro_rules = state == NestedMacroState :: MacroRulesBangName ;
431448 state = NestedMacroState :: Empty ;
432- let rest =
433- check_nested_macro ( psess, node_id, macro_rules, & del. tts , & nested_macros, guar) ;
449+ let rest = check_nested_macro (
450+ psess,
451+ node_id,
452+ macro_rules,
453+ & del. tts ,
454+ & nested_macros,
455+ collect,
456+ guar,
457+ ) ;
434458 // If we did not check the whole macro definition, then check the rest as if outside
435459 // the macro definition.
436460 check_nested_occurrences (
@@ -440,6 +464,7 @@ fn check_nested_occurrences(
440464 macros,
441465 binders,
442466 ops,
467+ collect,
443468 guar,
444469 ) ;
445470 }
@@ -452,7 +477,7 @@ fn check_nested_occurrences(
452477 ( NestedMacroState :: Macro , & TokenTree :: MetaVar ( ..) ) => {
453478 state = NestedMacroState :: MacroName ;
454479 // We check that the meta-variable is correctly used.
455- check_occurrences ( psess, node_id, tt, macros, binders, ops, guar) ;
480+ check_occurrences ( psess, node_id, tt, macros, binders, ops, collect , guar) ;
456481 }
457482 ( NestedMacroState :: MacroName , TokenTree :: Delimited ( .., del) )
458483 if del. delim == Delimiter :: Parenthesis =>
@@ -466,6 +491,7 @@ fn check_nested_occurrences(
466491 & nested_macros,
467492 & mut nested_binders,
468493 & Stack :: Empty ,
494+ collect,
469495 guar,
470496 ) ;
471497 }
@@ -480,12 +506,13 @@ fn check_nested_occurrences(
480506 & nested_macros,
481507 & nested_binders,
482508 & Stack :: Empty ,
509+ collect,
483510 guar,
484511 ) ;
485512 }
486513 ( _, tt) => {
487514 state = NestedMacroState :: Empty ;
488- check_occurrences ( psess, node_id, tt, macros, binders, ops, guar) ;
515+ check_occurrences ( psess, node_id, tt, macros, binders, ops, collect , guar) ;
489516 }
490517 }
491518 }
@@ -504,13 +531,15 @@ fn check_nested_occurrences(
504531/// - `macro_rules` specifies whether the macro is `macro_rules`
505532/// - `tts` is checked as a list of (LHS) => {RHS}
506533/// - `macros` is the stack of outer macros
534+ /// - `collect` is passed down through to the macro checking code (but is already recursive)
507535/// - `guar` is set in case of errors
508536fn check_nested_macro (
509537 psess : & ParseSess ,
510538 node_id : NodeId ,
511539 macro_rules : bool ,
512540 tts : & [ TokenTree ] ,
513541 macros : & Stack < ' _ , MacroState < ' _ > > ,
542+ collect : & mut ForceCollect ,
514543 guar : & mut Option < ErrorGuaranteed > ,
515544) -> usize {
516545 let n = tts. len ( ) ;
@@ -528,8 +557,8 @@ fn check_nested_macro(
528557 let lhs = & tts[ i] ;
529558 let rhs = & tts[ i + 2 ] ;
530559 let mut binders = Binders :: default ( ) ;
531- check_binders ( psess, node_id, lhs, macros, & mut binders, & Stack :: Empty , guar) ;
532- check_occurrences ( psess, node_id, rhs, macros, & binders, & Stack :: Empty , guar) ;
560+ check_binders ( psess, node_id, lhs, macros, & mut binders, & Stack :: Empty , collect , guar) ;
561+ check_occurrences ( psess, node_id, rhs, macros, & binders, & Stack :: Empty , collect , guar) ;
533562 // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated,
534563 // we increment our checked position by how many token trees we already checked (the 3
535564 // above) before checking for the separator.
0 commit comments