@@ -109,6 +109,7 @@ use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
109
109
use rustc_ast:: { DUMMY_NODE_ID , NodeId } ;
110
110
use rustc_data_structures:: fx:: FxHashMap ;
111
111
use rustc_errors:: DecorateDiagCompat ;
112
+ use rustc_parse:: parser:: ForceCollect ;
112
113
use rustc_session:: lint:: builtin:: META_VARIABLE_MISUSE ;
113
114
use rustc_session:: parse:: ParseSess ;
114
115
use rustc_span:: { ErrorGuaranteed , MacroRulesNormalizedIdent , Span , kw} ;
@@ -193,20 +194,23 @@ struct MacroState<'a> {
193
194
/// - `psess` is used to emit diagnostics and lints
194
195
/// - `node_id` is used to emit lints
195
196
/// - `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)
196
198
pub ( super ) fn check_meta_variables (
197
199
psess : & ParseSess ,
198
200
node_id : NodeId ,
199
201
args : Option < & TokenTree > ,
200
202
lhs : & TokenTree ,
201
203
rhs : & TokenTree ,
204
+ collect : & mut ForceCollect ,
202
205
) -> Result < ( ) , ErrorGuaranteed > {
203
206
let mut guar = None ;
204
207
let mut binders = Binders :: default ( ) ;
208
+ let ops = & Stack :: Empty ;
205
209
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) ;
207
211
}
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) ;
210
214
guar. map_or ( Ok ( ( ) ) , Err )
211
215
}
212
216
@@ -220,6 +224,7 @@ pub(super) fn check_meta_variables(
220
224
/// - `macros` is the stack of possible outer macros
221
225
/// - `binders` contains the binders of the LHS
222
226
/// - `ops` is the stack of Kleene operators from the LHS
227
+ /// - `collect` is updated to recursive if we encounter any metadata expressions
223
228
/// - `guar` is set in case of errors
224
229
fn check_binders (
225
230
psess : & ParseSess ,
@@ -228,6 +233,7 @@ fn check_binders(
228
233
macros : & Stack < ' _ , MacroState < ' _ > > ,
229
234
binders : & mut Binders ,
230
235
ops : & Stack < ' _ , KleeneToken > ,
236
+ collect : & mut ForceCollect ,
231
237
guar : & mut Option < ErrorGuaranteed > ,
232
238
) {
233
239
match * lhs {
@@ -255,7 +261,7 @@ fn check_binders(
255
261
binders. insert ( name, BinderInfo { span, ops : ops. into ( ) } ) ;
256
262
} else {
257
263
// 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) ;
259
265
}
260
266
}
261
267
// Similarly, this can only happen when checking a toplevel macro.
@@ -280,13 +286,13 @@ fn check_binders(
280
286
TokenTree :: MetaVarExpr ( ..) => { }
281
287
TokenTree :: Delimited ( .., ref del) => {
282
288
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) ;
284
290
}
285
291
}
286
292
TokenTree :: Sequence ( _, ref seq) => {
287
293
let ops = ops. push ( seq. kleene ) ;
288
294
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) ;
290
296
}
291
297
}
292
298
}
@@ -316,6 +322,7 @@ fn get_binder_info<'a>(
316
322
/// - `macros` is the stack of possible outer macros
317
323
/// - `binders` contains the binders of the associated LHS
318
324
/// - `ops` is the stack of Kleene operators from the RHS
325
+ /// - `collect` is updated to recursive if we encounter any metadata expressions
319
326
/// - `guar` is set in case of errors
320
327
fn check_occurrences (
321
328
psess : & ParseSess ,
@@ -324,6 +331,7 @@ fn check_occurrences(
324
331
macros : & Stack < ' _ , MacroState < ' _ > > ,
325
332
binders : & Binders ,
326
333
ops : & Stack < ' _ , KleeneToken > ,
334
+ collect : & mut ForceCollect ,
327
335
guar : & mut Option < ErrorGuaranteed > ,
328
336
) {
329
337
match * rhs {
@@ -336,17 +344,21 @@ fn check_occurrences(
336
344
check_ops_is_prefix ( psess, node_id, macros, binders, ops, span, name) ;
337
345
}
338
346
TokenTree :: MetaVarExpr ( dl, ref mve) => {
347
+ // Require recursive token collection if we have any metadata expressions
348
+ * collect = ForceCollect :: Recursive ;
339
349
mve. for_each_metavar ( ( ) , |_, ident| {
340
350
let name = MacroRulesNormalizedIdent :: new ( * ident) ;
341
351
check_ops_is_prefix ( psess, node_id, macros, binders, ops, dl. entire ( ) , name) ;
342
352
} ) ;
343
353
}
344
354
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) ;
346
356
}
347
357
TokenTree :: Sequence ( _, ref seq) => {
348
358
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
+ ) ;
350
362
}
351
363
}
352
364
}
@@ -381,6 +393,7 @@ enum NestedMacroState {
381
393
/// - `macros` is the stack of possible outer macros
382
394
/// - `binders` contains the binders of the associated LHS
383
395
/// - `ops` is the stack of Kleene operators from the RHS
396
+ /// - `collect` is updated to recursive if we encounter metadata expressions or nested macros
384
397
/// - `guar` is set in case of errors
385
398
fn check_nested_occurrences (
386
399
psess : & ParseSess ,
@@ -389,6 +402,7 @@ fn check_nested_occurrences(
389
402
macros : & Stack < ' _ , MacroState < ' _ > > ,
390
403
binders : & Binders ,
391
404
ops : & Stack < ' _ , KleeneToken > ,
405
+ collect : & mut ForceCollect ,
392
406
guar : & mut Option < ErrorGuaranteed > ,
393
407
) {
394
408
let mut state = NestedMacroState :: Empty ;
@@ -421,16 +435,26 @@ fn check_nested_occurrences(
421
435
( NestedMacroState :: MacroRulesBang , & TokenTree :: MetaVar ( ..) ) => {
422
436
state = NestedMacroState :: MacroRulesBangName ;
423
437
// 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) ;
425
439
}
426
440
( NestedMacroState :: MacroRulesBangName , TokenTree :: Delimited ( .., del) )
427
441
| ( NestedMacroState :: MacroName , TokenTree :: Delimited ( .., del) )
428
442
if del. delim == Delimiter :: Brace =>
429
443
{
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 ;
430
447
let macro_rules = state == NestedMacroState :: MacroRulesBangName ;
431
448
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
+ ) ;
434
458
// If we did not check the whole macro definition, then check the rest as if outside
435
459
// the macro definition.
436
460
check_nested_occurrences (
@@ -440,6 +464,7 @@ fn check_nested_occurrences(
440
464
macros,
441
465
binders,
442
466
ops,
467
+ collect,
443
468
guar,
444
469
) ;
445
470
}
@@ -452,7 +477,7 @@ fn check_nested_occurrences(
452
477
( NestedMacroState :: Macro , & TokenTree :: MetaVar ( ..) ) => {
453
478
state = NestedMacroState :: MacroName ;
454
479
// 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) ;
456
481
}
457
482
( NestedMacroState :: MacroName , TokenTree :: Delimited ( .., del) )
458
483
if del. delim == Delimiter :: Parenthesis =>
@@ -466,6 +491,7 @@ fn check_nested_occurrences(
466
491
& nested_macros,
467
492
& mut nested_binders,
468
493
& Stack :: Empty ,
494
+ collect,
469
495
guar,
470
496
) ;
471
497
}
@@ -480,12 +506,13 @@ fn check_nested_occurrences(
480
506
& nested_macros,
481
507
& nested_binders,
482
508
& Stack :: Empty ,
509
+ collect,
483
510
guar,
484
511
) ;
485
512
}
486
513
( _, tt) => {
487
514
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) ;
489
516
}
490
517
}
491
518
}
@@ -504,13 +531,15 @@ fn check_nested_occurrences(
504
531
/// - `macro_rules` specifies whether the macro is `macro_rules`
505
532
/// - `tts` is checked as a list of (LHS) => {RHS}
506
533
/// - `macros` is the stack of outer macros
534
+ /// - `collect` is passed down through to the macro checking code (but is already recursive)
507
535
/// - `guar` is set in case of errors
508
536
fn check_nested_macro (
509
537
psess : & ParseSess ,
510
538
node_id : NodeId ,
511
539
macro_rules : bool ,
512
540
tts : & [ TokenTree ] ,
513
541
macros : & Stack < ' _ , MacroState < ' _ > > ,
542
+ collect : & mut ForceCollect ,
514
543
guar : & mut Option < ErrorGuaranteed > ,
515
544
) -> usize {
516
545
let n = tts. len ( ) ;
@@ -528,8 +557,8 @@ fn check_nested_macro(
528
557
let lhs = & tts[ i] ;
529
558
let rhs = & tts[ i + 2 ] ;
530
559
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) ;
533
562
// Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated,
534
563
// we increment our checked position by how many token trees we already checked (the 3
535
564
// above) before checking for the separator.
0 commit comments