rustc_expand/mbe/
macro_rules.rs

1use std::borrow::Cow;
2use std::collections::hash_map::Entry;
3use std::{mem, slice};
4
5use ast::token::IdentIsRaw;
6use rustc_ast::attr::AttributeExt;
7use rustc_ast::token::NtPatKind::*;
8use rustc_ast::token::TokenKind::*;
9use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
10use rustc_ast::tokenstream::{DelimSpan, TokenStream};
11use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
12use rustc_ast_pretty::pprust;
13use rustc_attr_parsing::{self as attr, TransparencyError};
14use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
15use rustc_errors::{Applicability, ErrorGuaranteed};
16use rustc_feature::Features;
17use rustc_lint_defs::BuiltinLintDiag;
18use rustc_lint_defs::builtin::{
19    RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
20};
21use rustc_parse::parser::{ParseNtResult, Parser, Recovery};
22use rustc_session::Session;
23use rustc_session::parse::ParseSess;
24use rustc_span::edition::Edition;
25use rustc_span::hygiene::Transparency;
26use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, kw, sym};
27use tracing::{debug, instrument, trace, trace_span};
28
29use super::diagnostics;
30use super::macro_parser::{NamedMatches, NamedParseResult};
31use crate::base::{
32    DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension,
33    SyntaxExtensionKind, TTMacroExpander,
34};
35use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment};
36use crate::mbe;
37use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
38use crate::mbe::macro_check;
39use crate::mbe::macro_parser::NamedMatch::*;
40use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
41use crate::mbe::transcribe::transcribe;
42
43pub(crate) struct ParserAnyMacro<'a> {
44    parser: Parser<'a>,
45
46    /// Span of the expansion site of the macro this parser is for
47    site_span: Span,
48    /// The ident of the macro we're parsing
49    macro_ident: Ident,
50    lint_node_id: NodeId,
51    is_trailing_mac: bool,
52    arm_span: Span,
53    /// Whether or not this macro is defined in the current crate
54    is_local: bool,
55}
56
57impl<'a> ParserAnyMacro<'a> {
58    pub(crate) fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
59        let ParserAnyMacro {
60            site_span,
61            macro_ident,
62            ref mut parser,
63            lint_node_id,
64            arm_span,
65            is_trailing_mac,
66            is_local,
67        } = *self;
68        let snapshot = &mut parser.create_snapshot_for_diagnostic();
69        let fragment = match parse_ast_fragment(parser, kind) {
70            Ok(f) => f,
71            Err(err) => {
72                let guar = diagnostics::emit_frag_parse_err(
73                    err, parser, snapshot, site_span, arm_span, kind,
74                );
75                return kind.dummy(site_span, guar);
76            }
77        };
78
79        // We allow semicolons at the end of expressions -- e.g., the semicolon in
80        // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
81        // but `m!()` is allowed in expression positions (cf. issue #34706).
82        if kind == AstFragmentKind::Expr && parser.token == token::Semi {
83            if is_local {
84                parser.psess.buffer_lint(
85                    SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
86                    parser.token.span,
87                    lint_node_id,
88                    BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident),
89                );
90            }
91            parser.bump();
92        }
93
94        // Make sure we don't have any tokens left to parse so we don't silently drop anything.
95        let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
96        ensure_complete_parse(parser, &path, kind.name(), site_span);
97        fragment
98    }
99}
100
101struct MacroRulesMacroExpander {
102    node_id: NodeId,
103    name: Ident,
104    span: Span,
105    transparency: Transparency,
106    lhses: Vec<Vec<MatcherLoc>>,
107    rhses: Vec<mbe::TokenTree>,
108}
109
110impl TTMacroExpander for MacroRulesMacroExpander {
111    fn expand<'cx>(
112        &self,
113        cx: &'cx mut ExtCtxt<'_>,
114        sp: Span,
115        input: TokenStream,
116    ) -> MacroExpanderResult<'cx> {
117        ExpandResult::Ready(expand_macro(
118            cx,
119            sp,
120            self.span,
121            self.node_id,
122            self.name,
123            self.transparency,
124            input,
125            &self.lhses,
126            &self.rhses,
127        ))
128    }
129}
130
131struct DummyExpander(ErrorGuaranteed);
132
133impl TTMacroExpander for DummyExpander {
134    fn expand<'cx>(
135        &self,
136        _: &'cx mut ExtCtxt<'_>,
137        span: Span,
138        _: TokenStream,
139    ) -> ExpandResult<Box<dyn MacResult + 'cx>, ()> {
140        ExpandResult::Ready(DummyResult::any(span, self.0))
141    }
142}
143
144fn trace_macros_note(cx_expansions: &mut FxIndexMap<Span, Vec<String>>, sp: Span, message: String) {
145    let sp = sp.macro_backtrace().last().map_or(sp, |trace| trace.call_site);
146    cx_expansions.entry(sp).or_default().push(message);
147}
148
149pub(super) trait Tracker<'matcher> {
150    /// The contents of `ParseResult::Failure`.
151    type Failure;
152
153    /// Arm failed to match. If the token is `token::Eof`, it indicates an unexpected
154    /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
155    /// The usize is the approximate position of the token in the input token stream.
156    fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure;
157
158    /// This is called before trying to match next MatcherLoc on the current token.
159    fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {}
160
161    /// This is called after an arm has been parsed, either successfully or unsuccessfully. When
162    /// this is called, `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
163    fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {}
164
165    /// For tracing.
166    fn description() -> &'static str;
167
168    fn recovery() -> Recovery {
169        Recovery::Forbidden
170    }
171
172    fn set_expected_token(&mut self, _tok: &'matcher Token) {}
173    fn get_expected_token(&self) -> Option<&'matcher Token> {
174        None
175    }
176}
177
178/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to
179/// monomorphization.
180pub(super) struct NoopTracker;
181
182impl<'matcher> Tracker<'matcher> for NoopTracker {
183    type Failure = ();
184
185    fn build_failure(_tok: Token, _position: u32, _msg: &'static str) -> Self::Failure {}
186
187    fn description() -> &'static str {
188        "none"
189    }
190}
191
192/// Expands the rules based macro defined by `lhses` and `rhses` for a given
193/// input `arg`.
194#[instrument(skip(cx, transparency, arg, lhses, rhses))]
195fn expand_macro<'cx>(
196    cx: &'cx mut ExtCtxt<'_>,
197    sp: Span,
198    def_span: Span,
199    node_id: NodeId,
200    name: Ident,
201    transparency: Transparency,
202    arg: TokenStream,
203    lhses: &[Vec<MatcherLoc>],
204    rhses: &[mbe::TokenTree],
205) -> Box<dyn MacResult + 'cx> {
206    let psess = &cx.sess.psess;
207    // Macros defined in the current crate have a real node id,
208    // whereas macros from an external crate have a dummy id.
209    let is_local = node_id != DUMMY_NODE_ID;
210
211    if cx.trace_macros() {
212        let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg));
213        trace_macros_note(&mut cx.expansions, sp, msg);
214    }
215
216    // Track nothing for the best performance.
217    let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut NoopTracker);
218
219    match try_success_result {
220        Ok((i, named_matches)) => {
221            let (rhs, rhs_span): (&mbe::Delimited, DelimSpan) = match &rhses[i] {
222                mbe::TokenTree::Delimited(span, _, delimited) => (&delimited, *span),
223                _ => cx.dcx().span_bug(sp, "malformed macro rhs"),
224            };
225            let arm_span = rhses[i].span();
226
227            // rhs has holes ( `$id` and `$(...)` that need filled)
228            let id = cx.current_expansion.id;
229            let tts = match transcribe(psess, &named_matches, rhs, rhs_span, transparency, id) {
230                Ok(tts) => tts,
231                Err(err) => {
232                    let guar = err.emit();
233                    return DummyResult::any(arm_span, guar);
234                }
235            };
236
237            if cx.trace_macros() {
238                let msg = format!("to `{}`", pprust::tts_to_string(&tts));
239                trace_macros_note(&mut cx.expansions, sp, msg);
240            }
241
242            let p = Parser::new(psess, tts, None);
243
244            if is_local {
245                cx.resolver.record_macro_rule_usage(node_id, i);
246            }
247
248            // Let the context choose how to interpret the result.
249            // Weird, but useful for X-macros.
250            Box::new(ParserAnyMacro {
251                parser: p,
252
253                // Pass along the original expansion site and the name of the macro
254                // so we can print a useful error message if the parse of the expanded
255                // macro leaves unparsed tokens.
256                site_span: sp,
257                macro_ident: name,
258                lint_node_id: cx.current_expansion.lint_node_id,
259                is_trailing_mac: cx.current_expansion.is_trailing_mac,
260                arm_span,
261                is_local,
262            })
263        }
264        Err(CanRetry::No(guar)) => {
265            debug!("Will not retry matching as an error was emitted already");
266            DummyResult::any(sp, guar)
267        }
268        Err(CanRetry::Yes) => {
269            // Retry and emit a better error.
270            let (span, guar) =
271                diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, lhses);
272            cx.trace_macros_diag();
273            DummyResult::any(span, guar)
274        }
275    }
276}
277
278pub(super) enum CanRetry {
279    Yes,
280    /// We are not allowed to retry macro expansion as a fatal error has been emitted already.
281    No(ErrorGuaranteed),
282}
283
284/// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful,
285/// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors
286/// correctly.
287#[instrument(level = "debug", skip(psess, arg, lhses, track), fields(tracking = %T::description()))]
288pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
289    psess: &ParseSess,
290    name: Ident,
291    arg: &TokenStream,
292    lhses: &'matcher [Vec<MatcherLoc>],
293    track: &mut T,
294) -> Result<(usize, NamedMatches), CanRetry> {
295    // We create a base parser that can be used for the "black box" parts.
296    // Every iteration needs a fresh copy of that parser. However, the parser
297    // is not mutated on many of the iterations, particularly when dealing with
298    // macros like this:
299    //
300    // macro_rules! foo {
301    //     ("a") => (A);
302    //     ("b") => (B);
303    //     ("c") => (C);
304    //     // ... etc. (maybe hundreds more)
305    // }
306    //
307    // as seen in the `html5ever` benchmark. We use a `Cow` so that the base
308    // parser is only cloned when necessary (upon mutation). Furthermore, we
309    // reinitialize the `Cow` with the base parser at the start of every
310    // iteration, so that any mutated parsers are not reused. This is all quite
311    // hacky, but speeds up the `html5ever` benchmark significantly. (Issue
312    // 68836 suggests a more comprehensive but more complex change to deal with
313    // this situation.)
314    let parser = parser_from_cx(psess, arg.clone(), T::recovery());
315    // Try each arm's matchers.
316    let mut tt_parser = TtParser::new(name);
317    for (i, lhs) in lhses.iter().enumerate() {
318        let _tracing_span = trace_span!("Matching arm", %i);
319
320        // Take a snapshot of the state of pre-expansion gating at this point.
321        // This is used so that if a matcher is not `Success(..)`ful,
322        // then the spans which became gated when parsing the unsuccessful matcher
323        // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
324        let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
325
326        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track);
327
328        track.after_arm(&result);
329
330        match result {
331            Success(named_matches) => {
332                debug!("Parsed arm successfully");
333                // The matcher was `Success(..)`ful.
334                // Merge the gated spans from parsing the matcher with the preexisting ones.
335                psess.gated_spans.merge(gated_spans_snapshot);
336
337                return Ok((i, named_matches));
338            }
339            Failure(_) => {
340                trace!("Failed to match arm, trying the next one");
341                // Try the next arm.
342            }
343            Error(_, _) => {
344                debug!("Fatal error occurred during matching");
345                // We haven't emitted an error yet, so we can retry.
346                return Err(CanRetry::Yes);
347            }
348            ErrorReported(guarantee) => {
349                debug!("Fatal error occurred and was reported during matching");
350                // An error has been reported already, we cannot retry as that would cause duplicate errors.
351                return Err(CanRetry::No(guarantee));
352            }
353        }
354
355        // The matcher was not `Success(..)`ful.
356        // Restore to the state before snapshotting and maybe try again.
357        mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut());
358    }
359
360    Err(CanRetry::Yes)
361}
362
363// Note that macro-by-example's input is also matched against a token tree:
364//                   $( $lhs:tt => $rhs:tt );+
365//
366// Holy self-referential!
367
368/// Converts a macro item into a syntax extension.
369pub fn compile_declarative_macro(
370    sess: &Session,
371    features: &Features,
372    macro_def: &ast::MacroDef,
373    ident: Ident,
374    attrs: &[impl AttributeExt],
375    span: Span,
376    node_id: NodeId,
377    edition: Edition,
378) -> (SyntaxExtension, Vec<(usize, Span)>) {
379    let mk_syn_ext = |expander| {
380        SyntaxExtension::new(
381            sess,
382            features,
383            SyntaxExtensionKind::LegacyBang(expander),
384            span,
385            Vec::new(),
386            edition,
387            ident.name,
388            attrs,
389            node_id != DUMMY_NODE_ID,
390        )
391    };
392    let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new());
393
394    let dcx = sess.dcx();
395    let lhs_nm = Ident::new(sym::lhs, span);
396    let rhs_nm = Ident::new(sym::rhs, span);
397    let tt_spec = Some(NonterminalKind::TT);
398    let macro_rules = macro_def.macro_rules;
399
400    // Parse the macro_rules! invocation
401
402    // The pattern that macro_rules matches.
403    // The grammar for macro_rules! is:
404    // $( $lhs:tt => $rhs:tt );+
405    // ...quasiquoting this would be nice.
406    // These spans won't matter, anyways
407    let argument_gram = vec![
408        mbe::TokenTree::Sequence(
409            DelimSpan::dummy(),
410            mbe::SequenceRepetition {
411                tts: vec![
412                    mbe::TokenTree::MetaVarDecl(span, lhs_nm, tt_spec),
413                    mbe::TokenTree::token(token::FatArrow, span),
414                    mbe::TokenTree::MetaVarDecl(span, rhs_nm, tt_spec),
415                ],
416                separator: Some(Token::new(
417                    if macro_rules { token::Semi } else { token::Comma },
418                    span,
419                )),
420                kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, span),
421                num_captures: 2,
422            },
423        ),
424        // to phase into semicolon-termination instead of semicolon-separation
425        mbe::TokenTree::Sequence(
426            DelimSpan::dummy(),
427            mbe::SequenceRepetition {
428                tts: vec![mbe::TokenTree::token(
429                    if macro_rules { token::Semi } else { token::Comma },
430                    span,
431                )],
432                separator: None,
433                kleene: mbe::KleeneToken::new(mbe::KleeneOp::ZeroOrMore, span),
434                num_captures: 0,
435            },
436        ),
437    ];
438    // Convert it into `MatcherLoc` form.
439    let argument_gram = mbe::macro_parser::compute_locs(&argument_gram);
440
441    let create_parser = || {
442        let body = macro_def.body.tokens.clone();
443        Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS)
444    };
445
446    let parser = create_parser();
447    let mut tt_parser =
448        TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro }));
449    let argument_map =
450        match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) {
451            Success(m) => m,
452            Failure(()) => {
453                // The fast `NoopTracker` doesn't have any info on failure, so we need to retry it
454                // with another one that gives us the information we need.
455                // For this we need to reclone the macro body as the previous parser consumed it.
456                let retry_parser = create_parser();
457
458                let mut track = diagnostics::FailureForwarder::new();
459                let parse_result =
460                    tt_parser.parse_tt(&mut Cow::Owned(retry_parser), &argument_gram, &mut track);
461                let Failure((token, _, msg)) = parse_result else {
462                    unreachable!("matcher returned something other than Failure after retry");
463                };
464
465                let s = parse_failure_msg(&token, track.get_expected_token());
466                let sp = token.span.substitute_dummy(span);
467                let mut err = sess.dcx().struct_span_err(sp, s);
468                err.span_label(sp, msg);
469                annotate_doc_comment(&mut err, sess.source_map(), sp);
470                let guar = err.emit();
471                return dummy_syn_ext(guar);
472            }
473            Error(sp, msg) => {
474                let guar = sess.dcx().span_err(sp.substitute_dummy(span), msg);
475                return dummy_syn_ext(guar);
476            }
477            ErrorReported(guar) => {
478                return dummy_syn_ext(guar);
479            }
480        };
481
482    let mut guar = None;
483    let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
484
485    // Extract the arguments:
486    let lhses = match &argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] {
487        MatchedSeq(s) => s
488            .iter()
489            .map(|m| {
490                if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
491                    let tt = mbe::quoted::parse(
492                        &TokenStream::new(vec![tt.clone()]),
493                        true,
494                        sess,
495                        node_id,
496                        features,
497                        edition,
498                    )
499                    .pop()
500                    .unwrap();
501                    // We don't handle errors here, the driver will abort
502                    // after parsing/expansion. We can report every error in every macro this way.
503                    check_emission(check_lhs_nt_follows(sess, node_id, &tt));
504                    return tt;
505                }
506                sess.dcx().span_bug(span, "wrong-structured lhs")
507            })
508            .collect::<Vec<mbe::TokenTree>>(),
509        _ => sess.dcx().span_bug(span, "wrong-structured lhs"),
510    };
511
512    let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
513        MatchedSeq(s) => s
514            .iter()
515            .map(|m| {
516                if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
517                    return mbe::quoted::parse(
518                        &TokenStream::new(vec![tt.clone()]),
519                        false,
520                        sess,
521                        node_id,
522                        features,
523                        edition,
524                    )
525                    .pop()
526                    .unwrap();
527                }
528                sess.dcx().span_bug(span, "wrong-structured rhs")
529            })
530            .collect::<Vec<mbe::TokenTree>>(),
531        _ => sess.dcx().span_bug(span, "wrong-structured rhs"),
532    };
533
534    for rhs in &rhses {
535        check_emission(check_rhs(sess, rhs));
536    }
537
538    // Don't abort iteration early, so that errors for multiple lhses can be reported.
539    for lhs in &lhses {
540        check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(lhs)));
541    }
542
543    check_emission(macro_check::check_meta_variables(&sess.psess, node_id, span, &lhses, &rhses));
544
545    let (transparency, transparency_error) = attr::find_transparency(attrs, macro_rules);
546    match transparency_error {
547        Some(TransparencyError::UnknownTransparency(value, span)) => {
548            dcx.span_err(span, format!("unknown macro transparency: `{value}`"));
549        }
550        Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => {
551            dcx.span_err(vec![old_span, new_span], "multiple macro transparency attributes");
552        }
553        None => {}
554    }
555
556    if let Some(guar) = guar {
557        // To avoid warning noise, only consider the rules of this
558        // macro for the lint, if all rules are valid.
559        return dummy_syn_ext(guar);
560    }
561
562    // Compute the spans of the macro rules for unused rule linting.
563    // Also, we are only interested in non-foreign macros.
564    let rule_spans = if node_id != DUMMY_NODE_ID {
565        lhses
566            .iter()
567            .zip(rhses.iter())
568            .enumerate()
569            // If the rhs contains an invocation like compile_error!,
570            // don't consider the rule for the unused rule lint.
571            .filter(|(_idx, (_lhs, rhs))| !has_compile_error_macro(rhs))
572            // We only take the span of the lhs here,
573            // so that the spans of created warnings are smaller.
574            .map(|(idx, (lhs, _rhs))| (idx, lhs.span()))
575            .collect::<Vec<_>>()
576    } else {
577        Vec::new()
578    };
579
580    // Convert the lhses into `MatcherLoc` form, which is better for doing the
581    // actual matching.
582    let lhses = lhses
583        .iter()
584        .map(|lhs| {
585            // Ignore the delimiters around the matcher.
586            match lhs {
587                mbe::TokenTree::Delimited(.., delimited) => {
588                    mbe::macro_parser::compute_locs(&delimited.tts)
589                }
590                _ => sess.dcx().span_bug(span, "malformed macro lhs"),
591            }
592        })
593        .collect();
594
595    let expander = Box::new(MacroRulesMacroExpander {
596        name: ident,
597        span,
598        node_id,
599        transparency,
600        lhses,
601        rhses,
602    });
603    (mk_syn_ext(expander), rule_spans)
604}
605
606fn check_lhs_nt_follows(
607    sess: &Session,
608    node_id: NodeId,
609    lhs: &mbe::TokenTree,
610) -> Result<(), ErrorGuaranteed> {
611    // lhs is going to be like TokenTree::Delimited(...), where the
612    // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
613    if let mbe::TokenTree::Delimited(.., delimited) = lhs {
614        check_matcher(sess, node_id, &delimited.tts)
615    } else {
616        let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
617        Err(sess.dcx().span_err(lhs.span(), msg))
618    }
619}
620
621fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
622    if seq.separator.is_some() {
623        false
624    } else {
625        let mut is_empty = true;
626        let mut iter = seq.tts.iter().peekable();
627        while let Some(tt) = iter.next() {
628            match tt {
629                mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => {}
630                mbe::TokenTree::Token(t @ Token { kind: DocComment(..), .. }) => {
631                    let mut now = t;
632                    while let Some(&mbe::TokenTree::Token(
633                        next @ Token { kind: DocComment(..), .. },
634                    )) = iter.peek()
635                    {
636                        now = next;
637                        iter.next();
638                    }
639                    let span = t.span.to(now.span);
640                    sess.dcx().span_note(span, "doc comments are ignored in matcher position");
641                }
642                mbe::TokenTree::Sequence(_, sub_seq)
643                    if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
644                        || sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne) => {}
645                _ => is_empty = false,
646            }
647        }
648        is_empty
649    }
650}
651
652/// Checks that the lhs contains no repetition which could match an empty token
653/// tree, because then the matcher would hang indefinitely.
654fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(), ErrorGuaranteed> {
655    use mbe::TokenTree;
656    for tt in tts {
657        match tt {
658            TokenTree::Token(..)
659            | TokenTree::MetaVar(..)
660            | TokenTree::MetaVarDecl(..)
661            | TokenTree::MetaVarExpr(..) => (),
662            TokenTree::Delimited(.., del) => check_lhs_no_empty_seq(sess, &del.tts)?,
663            TokenTree::Sequence(span, seq) => {
664                if is_empty_token_tree(sess, seq) {
665                    let sp = span.entire();
666                    let guar = sess.dcx().span_err(sp, "repetition matches empty token tree");
667                    return Err(guar);
668                }
669                check_lhs_no_empty_seq(sess, &seq.tts)?
670            }
671        }
672    }
673
674    Ok(())
675}
676
677fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
678    match *rhs {
679        mbe::TokenTree::Delimited(..) => Ok(()),
680        _ => Err(sess.dcx().span_err(rhs.span(), "macro rhs must be delimited")),
681    }
682}
683
684fn check_matcher(
685    sess: &Session,
686    node_id: NodeId,
687    matcher: &[mbe::TokenTree],
688) -> Result<(), ErrorGuaranteed> {
689    let first_sets = FirstSets::new(matcher);
690    let empty_suffix = TokenSet::empty();
691    check_matcher_core(sess, node_id, &first_sets, matcher, &empty_suffix)?;
692    Ok(())
693}
694
695fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
696    match rhs {
697        mbe::TokenTree::Delimited(.., d) => {
698            let has_compile_error = d.tts.array_windows::<3>().any(|[ident, bang, args]| {
699                if let mbe::TokenTree::Token(ident) = ident
700                    && let TokenKind::Ident(ident, _) = ident.kind
701                    && ident == sym::compile_error
702                    && let mbe::TokenTree::Token(bang) = bang
703                    && let TokenKind::Not = bang.kind
704                    && let mbe::TokenTree::Delimited(.., del) = args
705                    && !del.delim.skip()
706                {
707                    true
708                } else {
709                    false
710                }
711            });
712            if has_compile_error { true } else { d.tts.iter().any(has_compile_error_macro) }
713        }
714        _ => false,
715    }
716}
717
718// `The FirstSets` for a matcher is a mapping from subsequences in the
719// matcher to the FIRST set for that subsequence.
720//
721// This mapping is partially precomputed via a backwards scan over the
722// token trees of the matcher, which provides a mapping from each
723// repetition sequence to its *first* set.
724//
725// (Hypothetically, sequences should be uniquely identifiable via their
726// spans, though perhaps that is false, e.g., for macro-generated macros
727// that do not try to inject artificial span information. My plan is
728// to try to catch such cases ahead of time and not include them in
729// the precomputed mapping.)
730struct FirstSets<'tt> {
731    // this maps each TokenTree::Sequence `$(tt ...) SEP OP` that is uniquely identified by its
732    // span in the original matcher to the First set for the inner sequence `tt ...`.
733    //
734    // If two sequences have the same span in a matcher, then map that
735    // span to None (invalidating the mapping here and forcing the code to
736    // use a slow path).
737    first: FxHashMap<Span, Option<TokenSet<'tt>>>,
738}
739
740impl<'tt> FirstSets<'tt> {
741    fn new(tts: &'tt [mbe::TokenTree]) -> FirstSets<'tt> {
742        use mbe::TokenTree;
743
744        let mut sets = FirstSets { first: FxHashMap::default() };
745        build_recur(&mut sets, tts);
746        return sets;
747
748        // walks backward over `tts`, returning the FIRST for `tts`
749        // and updating `sets` at the same time for all sequence
750        // substructure we find within `tts`.
751        fn build_recur<'tt>(sets: &mut FirstSets<'tt>, tts: &'tt [TokenTree]) -> TokenSet<'tt> {
752            let mut first = TokenSet::empty();
753            for tt in tts.iter().rev() {
754                match tt {
755                    TokenTree::Token(..)
756                    | TokenTree::MetaVar(..)
757                    | TokenTree::MetaVarDecl(..)
758                    | TokenTree::MetaVarExpr(..) => {
759                        first.replace_with(TtHandle::TtRef(tt));
760                    }
761                    TokenTree::Delimited(span, _, delimited) => {
762                        build_recur(sets, &delimited.tts);
763                        first.replace_with(TtHandle::from_token_kind(
764                            token::OpenDelim(delimited.delim),
765                            span.open,
766                        ));
767                    }
768                    TokenTree::Sequence(sp, seq_rep) => {
769                        let subfirst = build_recur(sets, &seq_rep.tts);
770
771                        match sets.first.entry(sp.entire()) {
772                            Entry::Vacant(vac) => {
773                                vac.insert(Some(subfirst.clone()));
774                            }
775                            Entry::Occupied(mut occ) => {
776                                // if there is already an entry, then a span must have collided.
777                                // This should not happen with typical macro_rules macros,
778                                // but syntax extensions need not maintain distinct spans,
779                                // so distinct syntax trees can be assigned the same span.
780                                // In such a case, the map cannot be trusted; so mark this
781                                // entry as unusable.
782                                occ.insert(None);
783                            }
784                        }
785
786                        // If the sequence contents can be empty, then the first
787                        // token could be the separator token itself.
788
789                        if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
790                            first.add_one_maybe(TtHandle::from_token(sep.clone()));
791                        }
792
793                        // Reverse scan: Sequence comes before `first`.
794                        if subfirst.maybe_empty
795                            || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrMore
796                            || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrOne
797                        {
798                            // If sequence is potentially empty, then
799                            // union them (preserving first emptiness).
800                            first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
801                        } else {
802                            // Otherwise, sequence guaranteed
803                            // non-empty; replace first.
804                            first = subfirst;
805                        }
806                    }
807                }
808            }
809
810            first
811        }
812    }
813
814    // walks forward over `tts` until all potential FIRST tokens are
815    // identified.
816    fn first(&self, tts: &'tt [mbe::TokenTree]) -> TokenSet<'tt> {
817        use mbe::TokenTree;
818
819        let mut first = TokenSet::empty();
820        for tt in tts.iter() {
821            assert!(first.maybe_empty);
822            match tt {
823                TokenTree::Token(..)
824                | TokenTree::MetaVar(..)
825                | TokenTree::MetaVarDecl(..)
826                | TokenTree::MetaVarExpr(..) => {
827                    first.add_one(TtHandle::TtRef(tt));
828                    return first;
829                }
830                TokenTree::Delimited(span, _, delimited) => {
831                    first.add_one(TtHandle::from_token_kind(
832                        token::OpenDelim(delimited.delim),
833                        span.open,
834                    ));
835                    return first;
836                }
837                TokenTree::Sequence(sp, seq_rep) => {
838                    let subfirst_owned;
839                    let subfirst = match self.first.get(&sp.entire()) {
840                        Some(Some(subfirst)) => subfirst,
841                        Some(&None) => {
842                            subfirst_owned = self.first(&seq_rep.tts);
843                            &subfirst_owned
844                        }
845                        None => {
846                            panic!("We missed a sequence during FirstSets construction");
847                        }
848                    };
849
850                    // If the sequence contents can be empty, then the first
851                    // token could be the separator token itself.
852                    if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
853                        first.add_one_maybe(TtHandle::from_token(sep.clone()));
854                    }
855
856                    assert!(first.maybe_empty);
857                    first.add_all(subfirst);
858                    if subfirst.maybe_empty
859                        || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrMore
860                        || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrOne
861                    {
862                        // Continue scanning for more first
863                        // tokens, but also make sure we
864                        // restore empty-tracking state.
865                        first.maybe_empty = true;
866                        continue;
867                    } else {
868                        return first;
869                    }
870                }
871            }
872        }
873
874        // we only exit the loop if `tts` was empty or if every
875        // element of `tts` matches the empty sequence.
876        assert!(first.maybe_empty);
877        first
878    }
879}
880
881// Most `mbe::TokenTree`s are preexisting in the matcher, but some are defined
882// implicitly, such as opening/closing delimiters and sequence repetition ops.
883// This type encapsulates both kinds. It implements `Clone` while avoiding the
884// need for `mbe::TokenTree` to implement `Clone`.
885#[derive(Debug)]
886enum TtHandle<'tt> {
887    /// This is used in most cases.
888    TtRef(&'tt mbe::TokenTree),
889
890    /// This is only used for implicit token trees. The `mbe::TokenTree` *must*
891    /// be `mbe::TokenTree::Token`. No other variants are allowed. We store an
892    /// `mbe::TokenTree` rather than a `Token` so that `get()` can return a
893    /// `&mbe::TokenTree`.
894    Token(mbe::TokenTree),
895}
896
897impl<'tt> TtHandle<'tt> {
898    fn from_token(tok: Token) -> Self {
899        TtHandle::Token(mbe::TokenTree::Token(tok))
900    }
901
902    fn from_token_kind(kind: TokenKind, span: Span) -> Self {
903        TtHandle::from_token(Token::new(kind, span))
904    }
905
906    // Get a reference to a token tree.
907    fn get(&'tt self) -> &'tt mbe::TokenTree {
908        match self {
909            TtHandle::TtRef(tt) => tt,
910            TtHandle::Token(token_tt) => token_tt,
911        }
912    }
913}
914
915impl<'tt> PartialEq for TtHandle<'tt> {
916    fn eq(&self, other: &TtHandle<'tt>) -> bool {
917        self.get() == other.get()
918    }
919}
920
921impl<'tt> Clone for TtHandle<'tt> {
922    fn clone(&self) -> Self {
923        match self {
924            TtHandle::TtRef(tt) => TtHandle::TtRef(tt),
925
926            // This variant *must* contain a `mbe::TokenTree::Token`, and not
927            // any other variant of `mbe::TokenTree`.
928            TtHandle::Token(mbe::TokenTree::Token(tok)) => {
929                TtHandle::Token(mbe::TokenTree::Token(tok.clone()))
930            }
931
932            _ => unreachable!(),
933        }
934    }
935}
936
937// A set of `mbe::TokenTree`s, which may include `TokenTree::Match`s
938// (for macro-by-example syntactic variables). It also carries the
939// `maybe_empty` flag; that is true if and only if the matcher can
940// match an empty token sequence.
941//
942// The First set is computed on submatchers like `$($a:expr b),* $(c)* d`,
943// which has corresponding FIRST = {$a:expr, c, d}.
944// Likewise, `$($a:expr b),* $(c)+ d` has FIRST = {$a:expr, c}.
945//
946// (Notably, we must allow for *-op to occur zero times.)
947#[derive(Clone, Debug)]
948struct TokenSet<'tt> {
949    tokens: Vec<TtHandle<'tt>>,
950    maybe_empty: bool,
951}
952
953impl<'tt> TokenSet<'tt> {
954    // Returns a set for the empty sequence.
955    fn empty() -> Self {
956        TokenSet { tokens: Vec::new(), maybe_empty: true }
957    }
958
959    // Returns the set `{ tok }` for the single-token (and thus
960    // non-empty) sequence [tok].
961    fn singleton(tt: TtHandle<'tt>) -> Self {
962        TokenSet { tokens: vec![tt], maybe_empty: false }
963    }
964
965    // Changes self to be the set `{ tok }`.
966    // Since `tok` is always present, marks self as non-empty.
967    fn replace_with(&mut self, tt: TtHandle<'tt>) {
968        self.tokens.clear();
969        self.tokens.push(tt);
970        self.maybe_empty = false;
971    }
972
973    // Changes self to be the empty set `{}`; meant for use when
974    // the particular token does not matter, but we want to
975    // record that it occurs.
976    fn replace_with_irrelevant(&mut self) {
977        self.tokens.clear();
978        self.maybe_empty = false;
979    }
980
981    // Adds `tok` to the set for `self`, marking sequence as non-empty.
982    fn add_one(&mut self, tt: TtHandle<'tt>) {
983        if !self.tokens.contains(&tt) {
984            self.tokens.push(tt);
985        }
986        self.maybe_empty = false;
987    }
988
989    // Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.)
990    fn add_one_maybe(&mut self, tt: TtHandle<'tt>) {
991        if !self.tokens.contains(&tt) {
992            self.tokens.push(tt);
993        }
994    }
995
996    // Adds all elements of `other` to this.
997    //
998    // (Since this is a set, we filter out duplicates.)
999    //
1000    // If `other` is potentially empty, then preserves the previous
1001    // setting of the empty flag of `self`. If `other` is guaranteed
1002    // non-empty, then `self` is marked non-empty.
1003    fn add_all(&mut self, other: &Self) {
1004        for tt in &other.tokens {
1005            if !self.tokens.contains(tt) {
1006                self.tokens.push(tt.clone());
1007            }
1008        }
1009        if !other.maybe_empty {
1010            self.maybe_empty = false;
1011        }
1012    }
1013}
1014
1015// Checks that `matcher` is internally consistent and that it
1016// can legally be followed by a token `N`, for all `N` in `follow`.
1017// (If `follow` is empty, then it imposes no constraint on
1018// the `matcher`.)
1019//
1020// Returns the set of NT tokens that could possibly come last in
1021// `matcher`. (If `matcher` matches the empty sequence, then
1022// `maybe_empty` will be set to true.)
1023//
1024// Requires that `first_sets` is pre-computed for `matcher`;
1025// see `FirstSets::new`.
1026fn check_matcher_core<'tt>(
1027    sess: &Session,
1028    node_id: NodeId,
1029    first_sets: &FirstSets<'tt>,
1030    matcher: &'tt [mbe::TokenTree],
1031    follow: &TokenSet<'tt>,
1032) -> Result<TokenSet<'tt>, ErrorGuaranteed> {
1033    use mbe::TokenTree;
1034
1035    let mut last = TokenSet::empty();
1036
1037    let mut errored = Ok(());
1038
1039    // 2. For each token and suffix  [T, SUFFIX] in M:
1040    // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
1041    // then ensure T can also be followed by any element of FOLLOW.
1042    'each_token: for i in 0..matcher.len() {
1043        let token = &matcher[i];
1044        let suffix = &matcher[i + 1..];
1045
1046        let build_suffix_first = || {
1047            let mut s = first_sets.first(suffix);
1048            if s.maybe_empty {
1049                s.add_all(follow);
1050            }
1051            s
1052        };
1053
1054        // (we build `suffix_first` on demand below; you can tell
1055        // which cases are supposed to fall through by looking for the
1056        // initialization of this variable.)
1057        let suffix_first;
1058
1059        // First, update `last` so that it corresponds to the set
1060        // of NT tokens that might end the sequence `... token`.
1061        match token {
1062            TokenTree::Token(..)
1063            | TokenTree::MetaVar(..)
1064            | TokenTree::MetaVarDecl(..)
1065            | TokenTree::MetaVarExpr(..) => {
1066                if token_can_be_followed_by_any(token) {
1067                    // don't need to track tokens that work with any,
1068                    last.replace_with_irrelevant();
1069                    // ... and don't need to check tokens that can be
1070                    // followed by anything against SUFFIX.
1071                    continue 'each_token;
1072                } else {
1073                    last.replace_with(TtHandle::TtRef(token));
1074                    suffix_first = build_suffix_first();
1075                }
1076            }
1077            TokenTree::Delimited(span, _, d) => {
1078                let my_suffix = TokenSet::singleton(TtHandle::from_token_kind(
1079                    token::CloseDelim(d.delim),
1080                    span.close,
1081                ));
1082                check_matcher_core(sess, node_id, first_sets, &d.tts, &my_suffix)?;
1083                // don't track non NT tokens
1084                last.replace_with_irrelevant();
1085
1086                // also, we don't need to check delimited sequences
1087                // against SUFFIX
1088                continue 'each_token;
1089            }
1090            TokenTree::Sequence(_, seq_rep) => {
1091                suffix_first = build_suffix_first();
1092                // The trick here: when we check the interior, we want
1093                // to include the separator (if any) as a potential
1094                // (but not guaranteed) element of FOLLOW. So in that
1095                // case, we make a temp copy of suffix and stuff
1096                // delimiter in there.
1097                //
1098                // FIXME: Should I first scan suffix_first to see if
1099                // delimiter is already in it before I go through the
1100                // work of cloning it? But then again, this way I may
1101                // get a "tighter" span?
1102                let mut new;
1103                let my_suffix = if let Some(sep) = &seq_rep.separator {
1104                    new = suffix_first.clone();
1105                    new.add_one_maybe(TtHandle::from_token(sep.clone()));
1106                    &new
1107                } else {
1108                    &suffix_first
1109                };
1110
1111                // At this point, `suffix_first` is built, and
1112                // `my_suffix` is some TokenSet that we can use
1113                // for checking the interior of `seq_rep`.
1114                let next = check_matcher_core(sess, node_id, first_sets, &seq_rep.tts, my_suffix)?;
1115                if next.maybe_empty {
1116                    last.add_all(&next);
1117                } else {
1118                    last = next;
1119                }
1120
1121                // the recursive call to check_matcher_core already ran the 'each_last
1122                // check below, so we can just keep going forward here.
1123                continue 'each_token;
1124            }
1125        }
1126
1127        // (`suffix_first` guaranteed initialized once reaching here.)
1128
1129        // Now `last` holds the complete set of NT tokens that could
1130        // end the sequence before SUFFIX. Check that every one works with `suffix`.
1131        for tt in &last.tokens {
1132            if let &TokenTree::MetaVarDecl(span, name, Some(kind)) = tt.get() {
1133                for next_token in &suffix_first.tokens {
1134                    let next_token = next_token.get();
1135
1136                    // Check if the old pat is used and the next token is `|`
1137                    // to warn about incompatibility with Rust 2021.
1138                    // We only emit this lint if we're parsing the original
1139                    // definition of this macro_rules, not while (re)parsing
1140                    // the macro when compiling another crate that is using the
1141                    // macro. (See #86567.)
1142                    // Macros defined in the current crate have a real node id,
1143                    // whereas macros from an external crate have a dummy id.
1144                    if node_id != DUMMY_NODE_ID
1145                        && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
1146                        && matches!(
1147                            next_token,
1148                            TokenTree::Token(token) if *token == BinOp(token::BinOpToken::Or)
1149                        )
1150                    {
1151                        // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
1152                        let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
1153                            span,
1154                            name,
1155                            Some(NonterminalKind::Pat(PatParam { inferred: false })),
1156                        ));
1157                        sess.psess.buffer_lint(
1158                            RUST_2021_INCOMPATIBLE_OR_PATTERNS,
1159                            span,
1160                            ast::CRATE_NODE_ID,
1161                            BuiltinLintDiag::OrPatternsBackCompat(span, suggestion),
1162                        );
1163                    }
1164                    match is_in_follow(next_token, kind) {
1165                        IsInFollow::Yes => {}
1166                        IsInFollow::No(possible) => {
1167                            let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1
1168                            {
1169                                "is"
1170                            } else {
1171                                "may be"
1172                            };
1173
1174                            let sp = next_token.span();
1175                            let mut err = sess.dcx().struct_span_err(
1176                                sp,
1177                                format!(
1178                                    "`${name}:{frag}` {may_be} followed by `{next}`, which \
1179                                     is not allowed for `{frag}` fragments",
1180                                    name = name,
1181                                    frag = kind,
1182                                    next = quoted_tt_to_string(next_token),
1183                                    may_be = may_be
1184                                ),
1185                            );
1186                            err.span_label(sp, format!("not allowed after `{kind}` fragments"));
1187
1188                            if kind == NonterminalKind::Pat(PatWithOr)
1189                                && sess.psess.edition.at_least_rust_2021()
1190                                && next_token.is_token(&BinOp(token::BinOpToken::Or))
1191                            {
1192                                let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
1193                                    span,
1194                                    name,
1195                                    Some(NonterminalKind::Pat(PatParam { inferred: false })),
1196                                ));
1197                                err.span_suggestion(
1198                                    span,
1199                                    "try a `pat_param` fragment specifier instead",
1200                                    suggestion,
1201                                    Applicability::MaybeIncorrect,
1202                                );
1203                            }
1204
1205                            let msg = "allowed there are: ";
1206                            match possible {
1207                                &[] => {}
1208                                &[t] => {
1209                                    err.note(format!(
1210                                        "only {t} is allowed after `{kind}` fragments",
1211                                    ));
1212                                }
1213                                ts => {
1214                                    err.note(format!(
1215                                        "{}{} or {}",
1216                                        msg,
1217                                        ts[..ts.len() - 1].to_vec().join(", "),
1218                                        ts[ts.len() - 1],
1219                                    ));
1220                                }
1221                            }
1222                            errored = Err(err.emit());
1223                        }
1224                    }
1225                }
1226            }
1227        }
1228    }
1229    errored?;
1230    Ok(last)
1231}
1232
1233fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
1234    if let mbe::TokenTree::MetaVarDecl(_, _, Some(kind)) = *tok {
1235        frag_can_be_followed_by_any(kind)
1236    } else {
1237        // (Non NT's can always be followed by anything in matchers.)
1238        true
1239    }
1240}
1241
1242/// Returns `true` if a fragment of type `frag` can be followed by any sort of
1243/// token. We use this (among other things) as a useful approximation
1244/// for when `frag` can be followed by a repetition like `$(...)*` or
1245/// `$(...)+`. In general, these can be a bit tricky to reason about,
1246/// so we adopt a conservative position that says that any fragment
1247/// specifier which consumes at most one token tree can be followed by
1248/// a fragment specifier (indeed, these fragments can be followed by
1249/// ANYTHING without fear of future compatibility hazards).
1250fn frag_can_be_followed_by_any(kind: NonterminalKind) -> bool {
1251    matches!(
1252        kind,
1253        NonterminalKind::Item           // always terminated by `}` or `;`
1254        | NonterminalKind::Block        // exactly one token tree
1255        | NonterminalKind::Ident        // exactly one token tree
1256        | NonterminalKind::Literal      // exactly one token tree
1257        | NonterminalKind::Meta         // exactly one token tree
1258        | NonterminalKind::Lifetime     // exactly one token tree
1259        | NonterminalKind::TT // exactly one token tree
1260    )
1261}
1262
1263enum IsInFollow {
1264    Yes,
1265    No(&'static [&'static str]),
1266}
1267
1268/// Returns `true` if `frag` can legally be followed by the token `tok`. For
1269/// fragments that can consume an unbounded number of tokens, `tok`
1270/// must be within a well-defined follow set. This is intended to
1271/// guarantee future compatibility: for example, without this rule, if
1272/// we expanded `expr` to include a new binary operator, we might
1273/// break macros that were relying on that binary operator as a
1274/// separator.
1275// when changing this do not forget to update doc/book/macros.md!
1276fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
1277    use mbe::TokenTree;
1278
1279    if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
1280        // closing a token tree can never be matched by any fragment;
1281        // iow, we always require that `(` and `)` match, etc.
1282        IsInFollow::Yes
1283    } else {
1284        match kind {
1285            NonterminalKind::Item => {
1286                // since items *must* be followed by either a `;` or a `}`, we can
1287                // accept anything after them
1288                IsInFollow::Yes
1289            }
1290            NonterminalKind::Block => {
1291                // anything can follow block, the braces provide an easy boundary to
1292                // maintain
1293                IsInFollow::Yes
1294            }
1295            NonterminalKind::Stmt | NonterminalKind::Expr(_) => {
1296                const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
1297                match tok {
1298                    TokenTree::Token(token) => match token.kind {
1299                        FatArrow | Comma | Semi => IsInFollow::Yes,
1300                        _ => IsInFollow::No(TOKENS),
1301                    },
1302                    _ => IsInFollow::No(TOKENS),
1303                }
1304            }
1305            NonterminalKind::Pat(PatParam { .. }) => {
1306                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
1307                match tok {
1308                    TokenTree::Token(token) => match token.kind {
1309                        FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes,
1310                        Ident(name, IdentIsRaw::No) if name == kw::If || name == kw::In => {
1311                            IsInFollow::Yes
1312                        }
1313                        _ => IsInFollow::No(TOKENS),
1314                    },
1315                    _ => IsInFollow::No(TOKENS),
1316                }
1317            }
1318            NonterminalKind::Pat(PatWithOr) => {
1319                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
1320                match tok {
1321                    TokenTree::Token(token) => match token.kind {
1322                        FatArrow | Comma | Eq => IsInFollow::Yes,
1323                        Ident(name, IdentIsRaw::No) if name == kw::If || name == kw::In => {
1324                            IsInFollow::Yes
1325                        }
1326                        _ => IsInFollow::No(TOKENS),
1327                    },
1328                    _ => IsInFollow::No(TOKENS),
1329                }
1330            }
1331            NonterminalKind::Path | NonterminalKind::Ty => {
1332                const TOKENS: &[&str] = &[
1333                    "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
1334                    "`where`",
1335                ];
1336                match tok {
1337                    TokenTree::Token(token) => match token.kind {
1338                        OpenDelim(Delimiter::Brace)
1339                        | OpenDelim(Delimiter::Bracket)
1340                        | Comma
1341                        | FatArrow
1342                        | Colon
1343                        | Eq
1344                        | Gt
1345                        | BinOp(token::Shr)
1346                        | Semi
1347                        | BinOp(token::Or) => IsInFollow::Yes,
1348                        Ident(name, IdentIsRaw::No) if name == kw::As || name == kw::Where => {
1349                            IsInFollow::Yes
1350                        }
1351                        _ => IsInFollow::No(TOKENS),
1352                    },
1353                    TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Block)) => IsInFollow::Yes,
1354                    _ => IsInFollow::No(TOKENS),
1355                }
1356            }
1357            NonterminalKind::Ident | NonterminalKind::Lifetime => {
1358                // being a single token, idents and lifetimes are harmless
1359                IsInFollow::Yes
1360            }
1361            NonterminalKind::Literal => {
1362                // literals may be of a single token, or two tokens (negative numbers)
1363                IsInFollow::Yes
1364            }
1365            NonterminalKind::Meta | NonterminalKind::TT => {
1366                // being either a single token or a delimited sequence, tt is
1367                // harmless
1368                IsInFollow::Yes
1369            }
1370            NonterminalKind::Vis => {
1371                // Explicitly disallow `priv`, on the off chance it comes back.
1372                const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
1373                match tok {
1374                    TokenTree::Token(token) => match token.kind {
1375                        Comma => IsInFollow::Yes,
1376                        Ident(_, IdentIsRaw::Yes) => IsInFollow::Yes,
1377                        Ident(name, _) if name != kw::Priv => IsInFollow::Yes,
1378                        _ => {
1379                            if token.can_begin_type() {
1380                                IsInFollow::Yes
1381                            } else {
1382                                IsInFollow::No(TOKENS)
1383                            }
1384                        }
1385                    },
1386                    TokenTree::MetaVarDecl(
1387                        _,
1388                        _,
1389                        Some(NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path),
1390                    ) => IsInFollow::Yes,
1391                    _ => IsInFollow::No(TOKENS),
1392                }
1393            }
1394        }
1395    }
1396}
1397
1398fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
1399    match tt {
1400        mbe::TokenTree::Token(token) => pprust::token_to_string(token).into(),
1401        mbe::TokenTree::MetaVar(_, name) => format!("${name}"),
1402        mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${name}:{kind}"),
1403        mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${name}:"),
1404        _ => panic!(
1405            "{}",
1406            "unexpected mbe::TokenTree::{Sequence or Delimited} \
1407             in follow set checker"
1408        ),
1409    }
1410}
1411
1412pub(super) fn parser_from_cx(
1413    psess: &ParseSess,
1414    mut tts: TokenStream,
1415    recovery: Recovery,
1416) -> Parser<'_> {
1417    tts.desugar_doc_comments();
1418    Parser::new(psess, tts, rustc_parse::MACRO_ARGUMENTS).recovery(recovery)
1419}