rustc_expand/mbe/
macro_rules.rs

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