@@ -77,9 +77,9 @@ use TokenTreeOrTokenTreeSlice::*;
7777use crate :: mbe:: { self , TokenTree } ;
7878
7979use rustc_ast:: token:: { self , DocComment , Nonterminal , Token } ;
80- use rustc_parse:: parser:: Parser ;
80+ use rustc_parse:: parser:: { OrPatNonterminalMode , Parser } ;
8181use rustc_session:: parse:: ParseSess ;
82- use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
82+ use rustc_span:: { edition :: Edition , symbol:: MacroRulesNormalizedIdent } ;
8383
8484use smallvec:: { smallvec, SmallVec } ;
8585
@@ -414,6 +414,18 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
414414 }
415415}
416416
417+ /// In edition 2015/18, `:pat` can only match `pat<no_top_alt>` because otherwise, we have
418+ /// breakage. As of edition 2021, `:pat` matches `top_pat`.
419+ ///
420+ /// See <https://github.com/rust-lang/rust/issues/54883> for more info.
421+ fn or_pat_mode ( edition : Edition ) -> OrPatNonterminalMode {
422+ match edition {
423+ Edition :: Edition2015 | Edition :: Edition2018 => OrPatNonterminalMode :: NoTopAlt ,
424+ // FIXME(mark-i-m): uncomment this when edition 2021 machinery is added.
425+ // Edition::Edition2021 => OrPatNonterminalMode::TopPat,
426+ }
427+ }
428+
417429/// Process the matcher positions of `cur_items` until it is empty. In the process, this will
418430/// produce more items in `next_items`, `eof_items`, and `bb_items`.
419431///
@@ -553,10 +565,14 @@ fn inner_parse_loop<'root, 'tt>(
553565
554566 // We need to match a metavar with a valid ident... call out to the black-box
555567 // parser by adding an item to `bb_items`.
556- TokenTree :: MetaVarDecl ( _, _, kind) => {
557- // Built-in nonterminals never start with these tokens,
558- // so we can eliminate them from consideration.
559- if Parser :: nonterminal_may_begin_with ( kind, token) {
568+ TokenTree :: MetaVarDecl ( span, _, kind) => {
569+ // Built-in nonterminals never start with these tokens, so we can eliminate
570+ // them from consideration.
571+ //
572+ // We use the span of the metavariable declaration to determine any
573+ // edition-specific matching behavior for non-terminals.
574+ if Parser :: nonterminal_may_begin_with ( kind, token, or_pat_mode ( span. edition ( ) ) )
575+ {
560576 bb_items. push ( item) ;
561577 }
562578 }
@@ -717,7 +733,10 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
717733 let mut item = bb_items. pop ( ) . unwrap ( ) ;
718734 if let TokenTree :: MetaVarDecl ( span, _, kind) = item. top_elts . get_tt ( item. idx ) {
719735 let match_cur = item. match_cur ;
720- let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
736+ // We use the span of the metavariable declaration to determine any
737+ // edition-specific matching behavior for non-terminals.
738+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind, or_pat_mode ( span. edition ( ) ) )
739+ {
721740 Err ( mut err) => {
722741 err. span_label (
723742 span,
0 commit comments