@@ -5,8 +5,9 @@ use rustc_ast::token::{self, Token};
5
5
use rustc_ast:: tokenstream;
6
6
use rustc_ast:: { NodeId , DUMMY_NODE_ID } ;
7
7
use 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 } ;
10
11
11
12
use rustc_span:: Span ;
12
13
@@ -29,10 +30,8 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
29
30
/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the
30
31
/// pattern, so we pass a parameter to indicate whether to expect them or not.
31
32
/// - `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.
36
35
///
37
36
/// # Returns
38
37
///
@@ -42,6 +41,7 @@ pub(super) fn parse(
42
41
expect_matchers : bool ,
43
42
sess : & ParseSess ,
44
43
node_id : NodeId ,
44
+ features : & Features ,
45
45
) -> Vec < TokenTree > {
46
46
// Will contain the final collection of `self::TokenTree`
47
47
let mut result = Vec :: new ( ) ;
@@ -52,7 +52,7 @@ pub(super) fn parse(
52
52
while let Some ( tree) = trees. next ( ) {
53
53
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
54
54
// 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 ) ;
56
56
match tree {
57
57
TokenTree :: MetaVar ( start_sp, ident) if expect_matchers => {
58
58
let span = match trees. next ( ) {
@@ -61,18 +61,39 @@ pub(super) fn parse(
61
61
Some ( tokenstream:: TokenTree :: Token ( token) ) => match token. ident ( ) {
62
62
Some ( ( frag, _) ) => {
63
63
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
+ )
73
74
. 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
+ ) ;
76
97
result. push ( TokenTree :: MetaVarDecl ( span, ident, Some ( kind) ) ) ;
77
98
continue ;
78
99
}
@@ -110,14 +131,14 @@ pub(super) fn parse(
110
131
/// converting `tree`
111
132
/// - `expect_matchers`: same as for `parse` (see above).
112
133
/// - `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.
115
135
fn parse_tree (
116
136
tree : tokenstream:: TokenTree ,
117
137
outer_trees : & mut impl Iterator < Item = tokenstream:: TokenTree > ,
118
138
expect_matchers : bool ,
119
139
sess : & ParseSess ,
120
140
node_id : NodeId ,
141
+ features : & Features ,
121
142
) -> TokenTree {
122
143
// Depending on what `tree` is, we could be parsing different parts of a macro
123
144
match tree {
@@ -145,7 +166,7 @@ fn parse_tree(
145
166
sess. span_diagnostic . span_err ( span. entire ( ) , & msg) ;
146
167
}
147
168
// 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 ) ;
149
170
// Get the Kleene operator and optional separator
150
171
let ( separator, kleene) =
151
172
parse_sep_and_kleene_op ( & mut trees, span. entire ( ) , sess) ;
@@ -196,7 +217,10 @@ fn parse_tree(
196
217
// descend into the delimited set and further parse it.
197
218
tokenstream:: TokenTree :: Delimited ( span, delim, tts) => TokenTree :: Delimited (
198
219
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
+ } ) ,
200
224
) ,
201
225
}
202
226
}
0 commit comments