@@ -77,9 +77,9 @@ use TokenTreeOrTokenTreeSlice::*;
77
77
use crate :: mbe:: { self , TokenTree } ;
78
78
79
79
use rustc_ast:: token:: { self , DocComment , Nonterminal , Token } ;
80
- use rustc_parse:: parser:: Parser ;
80
+ use rustc_parse:: parser:: { OrPatNonterminalMode , Parser } ;
81
81
use rustc_session:: parse:: ParseSess ;
82
- use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
82
+ use rustc_span:: { edition :: Edition , symbol:: MacroRulesNormalizedIdent } ;
83
83
84
84
use smallvec:: { smallvec, SmallVec } ;
85
85
@@ -414,6 +414,18 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
414
414
}
415
415
}
416
416
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
+
417
429
/// Process the matcher positions of `cur_items` until it is empty. In the process, this will
418
430
/// produce more items in `next_items`, `eof_items`, and `bb_items`.
419
431
///
@@ -556,10 +568,14 @@ fn inner_parse_loop<'root, 'tt>(
556
568
557
569
// We need to match a metavar with a valid ident... call out to the black-box
558
570
// 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
+ {
563
579
bb_items. push ( item) ;
564
580
}
565
581
}
@@ -720,7 +736,10 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
720
736
let mut item = bb_items. pop ( ) . unwrap ( ) ;
721
737
if let TokenTree :: MetaVarDecl ( span, _, kind) = item. top_elts . get_tt ( item. idx ) {
722
738
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
+ {
724
743
Err ( mut err) => {
725
744
err. span_label (
726
745
span,
0 commit comments