1
- use rustc_ast:: token:: { self , Delimiter , IdentIsRaw } ;
1
+ use rustc_ast:: token:: { self , Delimiter , IdentIsRaw , Token } ;
2
2
use rustc_ast:: tokenstream:: { RefTokenTreeCursor , TokenStream , TokenTree } ;
3
3
use rustc_ast:: { LitIntType , LitKind } ;
4
4
use rustc_ast_pretty:: pprust;
5
5
use rustc_errors:: { Applicability , PResult } ;
6
6
use rustc_macros:: { Decodable , Encodable } ;
7
7
use rustc_session:: parse:: ParseSess ;
8
8
use rustc_span:: symbol:: Ident ;
9
- use rustc_span:: Span ;
9
+ use rustc_span:: { Span , Symbol } ;
10
10
11
11
pub ( crate ) const RAW_IDENT_ERR : & str = "`${concat(..)}` currently does not support raw identifiers" ;
12
12
@@ -51,11 +51,18 @@ impl MetaVarExpr {
51
51
let mut result = Vec :: new ( ) ;
52
52
loop {
53
53
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) ?;
55
55
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)
57
64
} else {
58
- MetaVarExprConcatElem :: Ident ( element_ident )
65
+ MetaVarExprConcatElem :: Ident ( parse_ident_from_token ( psess , token ) ? )
59
66
} ;
60
67
result. push ( element) ;
61
68
if iter. look_ahead ( 0 ) . is_none ( ) {
@@ -105,11 +112,13 @@ impl MetaVarExpr {
105
112
106
113
#[ derive( Debug , Decodable , Encodable , PartialEq ) ]
107
114
pub ( 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.
110
117
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 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.
113
122
Var ( Ident ) ,
114
123
}
115
124
@@ -180,12 +189,14 @@ fn parse_ident<'psess>(
180
189
psess : & ' psess ParseSess ,
181
190
fallback_span : Span ,
182
191
) -> 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 > {
189
200
if let Some ( ( elem, is_raw) ) = token. ident ( ) {
190
201
if let IdentIsRaw :: Yes = is_raw {
191
202
return Err ( psess. dcx ( ) . struct_span_err ( elem. span , RAW_IDENT_ERR ) ) ;
@@ -205,6 +216,20 @@ fn parse_ident<'psess>(
205
216
Err ( err)
206
217
}
207
218
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
+
208
233
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
209
234
/// iterator is not modified and the result is `false`.
210
235
fn try_eat_comma ( iter : & mut RefTokenTreeCursor < ' _ > ) -> bool {
0 commit comments