@@ -7,9 +7,13 @@ use rustc_macros::{Decodable, Encodable};
77use rustc_session:: parse:: ParseSess ;
88use rustc_span:: { Ident , Span , Symbol } ;
99
10+ use crate :: errors:: { self , MveExpectedIdentContext } ;
11+
1012pub ( crate ) const RAW_IDENT_ERR : & str = "`${concat(..)}` currently does not support raw identifiers" ;
1113pub ( crate ) const UNSUPPORTED_CONCAT_ELEM_ERR : & str = "expected identifier or string literal" ;
1214
15+ const VALID_METAVAR_EXPR_NAMES : & str = "`count`, `ignore`, `index`, `len`, and `concat`" ;
16+
1317/// A meta-variable expression, for expansions based on properties of meta-variables.
1418#[ derive( Debug , PartialEq , Encodable , Decodable ) ]
1519pub ( crate ) enum MetaVarExpr {
@@ -39,7 +43,12 @@ impl MetaVarExpr {
3943 psess : & ' psess ParseSess ,
4044 ) -> PResult < ' psess , MetaVarExpr > {
4145 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+ ) ?;
4352 let Some ( TokenTree :: Delimited ( .., Delimiter :: Parenthesis , args) ) = iter. next ( ) else {
4453 let msg = "meta-variable expression parameter must be wrapped in parentheses" ;
4554 return Err ( psess. dcx ( ) . struct_span_err ( ident. span , msg) ) ;
@@ -51,7 +60,9 @@ impl MetaVarExpr {
5160 "count" => parse_count ( & mut iter, psess, ident. span ) ?,
5261 "ignore" => {
5362 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)
5566 }
5667 "index" => MetaVarExpr :: Index ( parse_depth ( & mut iter, psess, ident. span ) ?) ,
5768 "len" => MetaVarExpr :: Len ( parse_depth ( & mut iter, psess, ident. span ) ?) ,
@@ -168,7 +179,7 @@ fn parse_count<'psess>(
168179 span : Span ,
169180) -> PResult < ' psess , MetaVarExpr > {
170181 eat_dollar ( iter, psess, span) ?;
171- let ident = parse_ident ( iter, psess, span) ?;
182+ let ident = parse_ident ( iter, psess, span, MveExpectedIdentContext :: Count ) ?;
172183 let depth = if try_eat_comma ( iter) {
173184 if iter. peek ( ) . is_none ( ) {
174185 return Err ( psess. dcx ( ) . struct_span_err (
@@ -206,14 +217,32 @@ fn parse_depth<'psess>(
206217 }
207218}
208219
209- /// Parses an generic ident
220+ /// Tries to parse a generic ident. If this fails, create a missing identifier diagnostic with
221+ /// `context` explanation.
210222fn parse_ident < ' psess > (
211223 iter : & mut TokenStreamIter < ' _ > ,
212224 psess : & ' psess ParseSess ,
213225 fallback_span : Span ,
226+ context : MveExpectedIdentContext ,
214227) -> 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)
217246}
218247
219248fn parse_ident_from_token < ' psess > (
0 commit comments