@@ -5,8 +5,9 @@ use rustc_ast::token::{self, Token};
55use rustc_ast:: tokenstream;
66use rustc_ast:: { NodeId , DUMMY_NODE_ID } ;
77use rustc_ast_pretty:: pprust;
8- use rustc_session:: parse:: ParseSess ;
9- use rustc_span:: symbol:: { kw, Ident } ;
8+ use rustc_feature:: Features ;
9+ use rustc_session:: parse:: { feature_err, ParseSess } ;
10+ use rustc_span:: symbol:: { kw, sym, Ident } ;
1011
1112use rustc_span:: Span ;
1213
@@ -29,10 +30,8 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
2930/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the
3031/// pattern, so we pass a parameter to indicate whether to expect them or not.
3132/// - `sess`: the parsing session. Any errors will be emitted to this session.
32- /// - `features`, `attrs`: language feature flags and attributes so that we know whether to use
33- /// unstable features or not.
34- /// - `edition`: which edition are we in.
35- /// - `macro_node_id`: the NodeId of the macro we are parsing.
33+ /// - `node_id`: the NodeId of the macro we are parsing.
34+ /// - `features`: language features so we can do feature gating.
3635///
3736/// # Returns
3837///
@@ -42,6 +41,7 @@ pub(super) fn parse(
4241 expect_matchers : bool ,
4342 sess : & ParseSess ,
4443 node_id : NodeId ,
44+ features : & Features ,
4545) -> Vec < TokenTree > {
4646 // Will contain the final collection of `self::TokenTree`
4747 let mut result = Vec :: new ( ) ;
@@ -52,7 +52,7 @@ pub(super) fn parse(
5252 while let Some ( tree) = trees. next ( ) {
5353 // Given the parsed tree, if there is a metavar and we are expecting matchers, actually
5454 // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
55- let tree = parse_tree ( tree, & mut trees, expect_matchers, sess, node_id) ;
55+ let tree = parse_tree ( tree, & mut trees, expect_matchers, sess, node_id, features ) ;
5656 match tree {
5757 TokenTree :: MetaVar ( start_sp, ident) if expect_matchers => {
5858 let span = match trees. next ( ) {
@@ -61,18 +61,39 @@ pub(super) fn parse(
6161 Some ( tokenstream:: TokenTree :: Token ( token) ) => match token. ident ( ) {
6262 Some ( ( frag, _) ) => {
6363 let span = token. span . with_lo ( start_sp. lo ( ) ) ;
64- let kind = token:: NonterminalKind :: from_symbol ( frag. name )
65- . unwrap_or_else ( || {
66- let msg = format ! (
67- "invalid fragment specifier `{}`" ,
68- frag. name
69- ) ;
70- sess. span_diagnostic
71- . struct_span_err ( span, & msg)
72- . help ( VALID_FRAGMENT_NAMES_MSG )
64+
65+ match frag. name {
66+ sym:: pat2018 | sym:: pat2021 => {
67+ if !features. edition_macro_pats {
68+ feature_err (
69+ sess,
70+ sym:: edition_macro_pats,
71+ frag. span ,
72+ "`pat2018` and `pat2021` are unstable." ,
73+ )
7374 . emit ( ) ;
74- token:: NonterminalKind :: Ident
75- } ) ;
75+ }
76+ }
77+ _ => { }
78+ }
79+
80+ let kind =
81+ token:: NonterminalKind :: from_symbol ( frag. name , || {
82+ span. edition ( )
83+ } )
84+ . unwrap_or_else (
85+ || {
86+ let msg = format ! (
87+ "invalid fragment specifier `{}`" ,
88+ frag. name
89+ ) ;
90+ sess. span_diagnostic
91+ . struct_span_err ( span, & msg)
92+ . help ( VALID_FRAGMENT_NAMES_MSG )
93+ . emit ( ) ;
94+ token:: NonterminalKind :: Ident
95+ } ,
96+ ) ;
7697 result. push ( TokenTree :: MetaVarDecl ( span, ident, Some ( kind) ) ) ;
7798 continue ;
7899 }
@@ -110,14 +131,14 @@ pub(super) fn parse(
110131/// converting `tree`
111132/// - `expect_matchers`: same as for `parse` (see above).
112133/// - `sess`: the parsing session. Any errors will be emitted to this session.
113- /// - `features`, `attrs`: language feature flags and attributes so that we know whether to use
114- /// unstable features or not.
134+ /// - `features`: language features so we can do feature gating.
115135fn parse_tree (
116136 tree : tokenstream:: TokenTree ,
117137 outer_trees : & mut impl Iterator < Item = tokenstream:: TokenTree > ,
118138 expect_matchers : bool ,
119139 sess : & ParseSess ,
120140 node_id : NodeId ,
141+ features : & Features ,
121142) -> TokenTree {
122143 // Depending on what `tree` is, we could be parsing different parts of a macro
123144 match tree {
@@ -145,7 +166,7 @@ fn parse_tree(
145166 sess. span_diagnostic . span_err ( span. entire ( ) , & msg) ;
146167 }
147168 // Parse the contents of the sequence itself
148- let sequence = parse ( tts, expect_matchers, sess, node_id) ;
169+ let sequence = parse ( tts, expect_matchers, sess, node_id, features ) ;
149170 // Get the Kleene operator and optional separator
150171 let ( separator, kleene) =
151172 parse_sep_and_kleene_op ( & mut trees, span. entire ( ) , sess) ;
@@ -196,7 +217,10 @@ fn parse_tree(
196217 // descend into the delimited set and further parse it.
197218 tokenstream:: TokenTree :: Delimited ( span, delim, tts) => TokenTree :: Delimited (
198219 span,
199- Lrc :: new ( Delimited { delim, tts : parse ( tts, expect_matchers, sess, node_id) } ) ,
220+ Lrc :: new ( Delimited {
221+ delim,
222+ tts : parse ( tts, expect_matchers, sess, node_id, features) ,
223+ } ) ,
200224 ) ,
201225 }
202226}
0 commit comments