@@ -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///
@@ -556,10 +568,14 @@ fn inner_parse_loop<'root, 'tt>(
556568
557569 // We need to match a metavar with a valid ident... call out to the black-box
558570 // parser by adding an item to `bb_items`.
559- TokenTree :: MetaVarDecl ( _, _, kind) => {
560- // Built-in nonterminals never start with these tokens,
561- // so we can eliminate them from consideration.
562- if Parser :: nonterminal_may_begin_with ( kind, token) {
571+ TokenTree :: MetaVarDecl ( span, _, kind) => {
572+ // Built-in nonterminals never start with these tokens, so we can eliminate
573+ // them from consideration.
574+ //
575+ // We use the span of the metavariable declaration to determine any
576+ // edition-specific matching behavior for non-terminals.
577+ if Parser :: nonterminal_may_begin_with ( kind, token, or_pat_mode ( span. edition ( ) ) )
578+ {
563579 bb_items. push ( item) ;
564580 }
565581 }
@@ -720,7 +736,10 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
720736 let mut item = bb_items. pop ( ) . unwrap ( ) ;
721737 if let TokenTree :: MetaVarDecl ( span, _, kind) = item. top_elts . get_tt ( item. idx ) {
722738 let match_cur = item. match_cur ;
723- let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
739+ // We use the span of the metavariable declaration to determine any
740+ // edition-specific matching behavior for non-terminals.
741+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind, or_pat_mode ( span. edition ( ) ) )
742+ {
724743 Err ( mut err) => {
725744 err. span_label (
726745 span,
0 commit comments