1- use rustc_ast:: token:: { self , Delimiter , IdentIsRaw } ;
1+ use rustc_ast:: token:: { self , Delimiter , IdentIsRaw , Token } ;
22use rustc_ast:: tokenstream:: { RefTokenTreeCursor , TokenStream , TokenTree } ;
33use rustc_ast:: { LitIntType , LitKind } ;
44use rustc_ast_pretty:: pprust;
55use rustc_errors:: { Applicability , PResult } ;
66use rustc_macros:: { Decodable , Encodable } ;
77use rustc_session:: parse:: ParseSess ;
88use rustc_span:: symbol:: Ident ;
9- use rustc_span:: Span ;
9+ use rustc_span:: { Span , Symbol } ;
1010
1111pub ( crate ) const RAW_IDENT_ERR : & str = "`${concat(..)}` currently does not support raw identifiers" ;
1212
@@ -51,11 +51,18 @@ impl MetaVarExpr {
5151 let mut result = Vec :: new ( ) ;
5252 loop {
5353 let is_var = try_eat_dollar ( & mut iter) ;
54- let element_ident = parse_ident ( & mut iter, psess, outer_span) ?;
54+ let token = parse_token ( & mut iter, psess, outer_span) ?;
5555 let element = if is_var {
56- MetaVarExprConcatElem :: Var ( element_ident)
56+ MetaVarExprConcatElem :: Var ( parse_ident_from_token ( psess, token) ?)
57+ } else if let token:: TokenKind :: Literal ( token:: Lit {
58+ kind : token:: LitKind :: Char | token:: LitKind :: Integer | token:: LitKind :: Str ,
59+ symbol,
60+ suffix : None ,
61+ } ) = token. kind
62+ {
63+ MetaVarExprConcatElem :: Literal ( symbol)
5764 } else {
58- MetaVarExprConcatElem :: Ident ( element_ident )
65+ MetaVarExprConcatElem :: Ident ( parse_ident_from_token ( psess , token ) ? )
5966 } ;
6067 result. push ( element) ;
6168 if iter. look_ahead ( 0 ) . is_none ( ) {
@@ -105,11 +112,13 @@ impl MetaVarExpr {
105112
106113#[ derive( Debug , Decodable , Encodable , PartialEq ) ]
107114pub ( crate ) enum MetaVarExprConcatElem {
108- /// There is NO preceding dollar sign, which means that this identifier should be interpreted
109- /// as a literal.
115+ /// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
116+ /// interpreted as a literal.
110117 Ident ( Ident ) ,
111- /// There is a preceding dollar sign, which means that this identifier should be expanded
112- /// and interpreted as a variable.
118+ /// For example, a number or a raw string.
119+ Literal ( Symbol ) ,
120+ /// Identifier WITH a preceding dollar sign, which means that this identifier should be
121+ /// expanded and interpreted as a variable.
113122 Var ( Ident ) ,
114123}
115124
@@ -180,12 +189,14 @@ fn parse_ident<'psess>(
180189 psess : & ' psess ParseSess ,
181190 fallback_span : Span ,
182191) -> PResult < ' psess , Ident > {
183- let Some ( tt) = iter. next ( ) else {
184- return Err ( psess. dcx ( ) . struct_span_err ( fallback_span, "expected identifier" ) ) ;
185- } ;
186- let TokenTree :: Token ( token, _) = tt else {
187- return Err ( psess. dcx ( ) . struct_span_err ( tt. span ( ) , "expected identifier" ) ) ;
188- } ;
192+ let token = parse_token ( iter, psess, fallback_span) ?;
193+ parse_ident_from_token ( psess, token)
194+ }
195+
196+ fn parse_ident_from_token < ' psess > (
197+ psess : & ' psess ParseSess ,
198+ token : & Token ,
199+ ) -> PResult < ' psess , Ident > {
189200 if let Some ( ( elem, is_raw) ) = token. ident ( ) {
190201 if let IdentIsRaw :: Yes = is_raw {
191202 return Err ( psess. dcx ( ) . struct_span_err ( elem. span , RAW_IDENT_ERR ) ) ;
@@ -205,6 +216,20 @@ fn parse_ident<'psess>(
205216 Err ( err)
206217}
207218
219+ fn parse_token < ' psess , ' t > (
220+ iter : & mut RefTokenTreeCursor < ' t > ,
221+ psess : & ' psess ParseSess ,
222+ fallback_span : Span ,
223+ ) -> PResult < ' psess , & ' t Token > {
224+ let Some ( tt) = iter. next ( ) else {
225+ return Err ( psess. dcx ( ) . struct_span_err ( fallback_span, "expected identifier" ) ) ;
226+ } ;
227+ let TokenTree :: Token ( token, _) = tt else {
228+ return Err ( psess. dcx ( ) . struct_span_err ( tt. span ( ) , "expected identifier" ) ) ;
229+ } ;
230+ Ok ( token)
231+ }
232+
208233/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
209234/// iterator is not modified and the result is `false`.
210235fn try_eat_comma ( iter : & mut RefTokenTreeCursor < ' _ > ) -> bool {
0 commit comments