@@ -7,9 +7,13 @@ use rustc_macros::{Decodable, Encodable};
7
7
use rustc_session:: parse:: ParseSess ;
8
8
use rustc_span:: { Ident , Span , Symbol } ;
9
9
10
+ use crate :: errors:: { self , MveExpectedIdentContext } ;
11
+
10
12
pub ( crate ) const RAW_IDENT_ERR : & str = "`${concat(..)}` currently does not support raw identifiers" ;
11
13
pub ( crate ) const UNSUPPORTED_CONCAT_ELEM_ERR : & str = "expected identifier or string literal" ;
12
14
15
+ const VALID_METAVAR_EXPR_NAMES : & str = "`count`, `ignore`, `index`, `len`, and `concat`" ;
16
+
13
17
/// A meta-variable expression, for expansions based on properties of meta-variables.
14
18
#[ derive( Debug , PartialEq , Encodable , Decodable ) ]
15
19
pub ( crate ) enum MetaVarExpr {
@@ -39,7 +43,12 @@ impl MetaVarExpr {
39
43
psess : & ' psess ParseSess ,
40
44
) -> PResult < ' psess , MetaVarExpr > {
41
45
let mut iter = input. iter ( ) ;
42
- let ident = parse_ident ( & mut iter, psess, outer_span) ?;
46
+ let ident = parse_ident (
47
+ & mut iter,
48
+ psess,
49
+ outer_span,
50
+ MveExpectedIdentContext :: ExprName { valid_expr_list : VALID_METAVAR_EXPR_NAMES } ,
51
+ ) ?;
43
52
let Some ( TokenTree :: Delimited ( .., Delimiter :: Parenthesis , args) ) = iter. next ( ) else {
44
53
let msg = "meta-variable expression parameter must be wrapped in parentheses" ;
45
54
return Err ( psess. dcx ( ) . struct_span_err ( ident. span , msg) ) ;
@@ -51,7 +60,9 @@ impl MetaVarExpr {
51
60
"count" => parse_count ( & mut iter, psess, ident. span ) ?,
52
61
"ignore" => {
53
62
eat_dollar ( & mut iter, psess, ident. span ) ?;
54
- MetaVarExpr :: Ignore ( parse_ident ( & mut iter, psess, ident. span ) ?)
63
+ let ident =
64
+ parse_ident ( & mut iter, psess, outer_span, MveExpectedIdentContext :: Ignore ) ?;
65
+ MetaVarExpr :: Ignore ( ident)
55
66
}
56
67
"index" => MetaVarExpr :: Index ( parse_depth ( & mut iter, psess, ident. span ) ?) ,
57
68
"len" => MetaVarExpr :: Len ( parse_depth ( & mut iter, psess, ident. span ) ?) ,
@@ -168,7 +179,7 @@ fn parse_count<'psess>(
168
179
span : Span ,
169
180
) -> PResult < ' psess , MetaVarExpr > {
170
181
eat_dollar ( iter, psess, span) ?;
171
- let ident = parse_ident ( iter, psess, span) ?;
182
+ let ident = parse_ident ( iter, psess, span, MveExpectedIdentContext :: Count ) ?;
172
183
let depth = if try_eat_comma ( iter) {
173
184
if iter. peek ( ) . is_none ( ) {
174
185
return Err ( psess. dcx ( ) . struct_span_err (
@@ -206,14 +217,32 @@ fn parse_depth<'psess>(
206
217
}
207
218
}
208
219
209
- /// Parses an generic ident
220
+ /// Tries to parse a generic ident. If this fails, create a missing identifier diagnostic with
221
+ /// `context` explanation.
210
222
fn parse_ident < ' psess > (
211
223
iter : & mut TokenStreamIter < ' _ > ,
212
224
psess : & ' psess ParseSess ,
213
225
fallback_span : Span ,
226
+ context : MveExpectedIdentContext ,
214
227
) -> PResult < ' psess , Ident > {
215
- let token = parse_token ( iter, psess, fallback_span) ?;
216
- parse_ident_from_token ( psess, token)
228
+ let Some ( tt) = iter. next ( ) else {
229
+ let err = errors:: MveExpectedIdent { span : fallback_span, not_ident_label : None , context } ;
230
+ return Err ( psess. dcx ( ) . create_err ( err) ) ;
231
+ } ;
232
+
233
+ let TokenTree :: Token ( token, _) = tt else {
234
+ let span = tt. span ( ) ;
235
+ let err = errors:: MveExpectedIdent { span, not_ident_label : Some ( span) , context } ;
236
+ return Err ( psess. dcx ( ) . create_err ( err) ) ;
237
+ } ;
238
+
239
+ let Some ( ( elem, _) ) = token. ident ( ) else {
240
+ let span = token. span ;
241
+ let err = errors:: MveExpectedIdent { span, not_ident_label : Some ( span) , context } ;
242
+ return Err ( psess. dcx ( ) . create_err ( err) ) ;
243
+ } ;
244
+
245
+ Ok ( elem)
217
246
}
218
247
219
248
fn parse_ident_from_token < ' psess > (
0 commit comments