1
- use rustc_ast:: token:: { self , Delimiter , IdentIsRaw } ;
1
+ use rustc_ast:: token:: { self , Delimiter , IdentIsRaw , Lit , Token , TokenKind } ;
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
+ pub ( crate ) const UNSUPPORTED_CONCAT_ELEM_ERR : & str = "expected identifier or string literal" ;
12
13
13
14
/// A meta-variable expression, for expansions based on properties of meta-variables.
14
15
#[ derive( Debug , PartialEq , Encodable , Decodable ) ]
@@ -51,11 +52,26 @@ impl MetaVarExpr {
51
52
let mut result = Vec :: new ( ) ;
52
53
loop {
53
54
let is_var = try_eat_dollar ( & mut iter) ;
54
- let element_ident = parse_ident ( & mut iter, psess, outer_span) ?;
55
+ let token = parse_token ( & mut iter, psess, outer_span) ?;
55
56
let element = if is_var {
56
- MetaVarExprConcatElem :: Var ( element_ident)
57
+ MetaVarExprConcatElem :: Var ( parse_ident_from_token ( psess, token) ?)
58
+ } else if let TokenKind :: Literal ( Lit {
59
+ kind : token:: LitKind :: Str ,
60
+ symbol,
61
+ suffix : None ,
62
+ } ) = token. kind
63
+ {
64
+ MetaVarExprConcatElem :: Literal ( symbol)
57
65
} else {
58
- MetaVarExprConcatElem :: Ident ( element_ident)
66
+ match parse_ident_from_token ( psess, token) {
67
+ Err ( err) => {
68
+ err. cancel ( ) ;
69
+ return Err ( psess
70
+ . dcx ( )
71
+ . struct_span_err ( token. span , UNSUPPORTED_CONCAT_ELEM_ERR ) ) ;
72
+ }
73
+ Ok ( elem) => MetaVarExprConcatElem :: Ident ( elem) ,
74
+ }
59
75
} ;
60
76
result. push ( element) ;
61
77
if iter. look_ahead ( 0 ) . is_none ( ) {
@@ -105,11 +121,13 @@ impl MetaVarExpr {
105
121
106
122
#[ derive( Debug , Decodable , Encodable , PartialEq ) ]
107
123
pub ( crate ) enum MetaVarExprConcatElem {
108
- /// There is NO preceding dollar sign, which means that this identifier should be interpreted
109
- /// as a literal.
124
+ /// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
125
+ /// interpreted as a literal.
110
126
Ident ( Ident ) ,
111
- /// There is a preceding dollar sign, which means that this identifier should be expanded
112
- /// and interpreted as a variable.
127
+ /// For example, a number or a string.
128
+ Literal ( Symbol ) ,
129
+ /// Identifier WITH a preceding dollar sign, which means that this identifier should be
130
+ /// expanded and interpreted as a variable.
113
131
Var ( Ident ) ,
114
132
}
115
133
@@ -158,7 +176,7 @@ fn parse_depth<'psess>(
158
176
span : Span ,
159
177
) -> PResult < ' psess , usize > {
160
178
let Some ( tt) = iter. next ( ) else { return Ok ( 0 ) } ;
161
- let TokenTree :: Token ( token :: Token { kind : token :: TokenKind :: Literal ( lit) , .. } , _) = tt else {
179
+ let TokenTree :: Token ( Token { kind : TokenKind :: Literal ( lit) , .. } , _) = tt else {
162
180
return Err ( psess
163
181
. dcx ( )
164
182
. struct_span_err ( span, "meta-variable expression depth must be a literal" ) ) ;
@@ -180,12 +198,14 @@ fn parse_ident<'psess>(
180
198
psess : & ' psess ParseSess ,
181
199
fallback_span : Span ,
182
200
) -> 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
- } ;
201
+ let token = parse_token ( iter, psess, fallback_span) ?;
202
+ parse_ident_from_token ( psess, token)
203
+ }
204
+
205
+ fn parse_ident_from_token < ' psess > (
206
+ psess : & ' psess ParseSess ,
207
+ token : & Token ,
208
+ ) -> PResult < ' psess , Ident > {
189
209
if let Some ( ( elem, is_raw) ) = token. ident ( ) {
190
210
if let IdentIsRaw :: Yes = is_raw {
191
211
return Err ( psess. dcx ( ) . struct_span_err ( elem. span , RAW_IDENT_ERR ) ) ;
@@ -205,10 +225,24 @@ fn parse_ident<'psess>(
205
225
Err ( err)
206
226
}
207
227
228
+ fn parse_token < ' psess , ' t > (
229
+ iter : & mut RefTokenTreeCursor < ' t > ,
230
+ psess : & ' psess ParseSess ,
231
+ fallback_span : Span ,
232
+ ) -> PResult < ' psess , & ' t Token > {
233
+ let Some ( tt) = iter. next ( ) else {
234
+ return Err ( psess. dcx ( ) . struct_span_err ( fallback_span, UNSUPPORTED_CONCAT_ELEM_ERR ) ) ;
235
+ } ;
236
+ let TokenTree :: Token ( token, _) = tt else {
237
+ return Err ( psess. dcx ( ) . struct_span_err ( tt. span ( ) , UNSUPPORTED_CONCAT_ELEM_ERR ) ) ;
238
+ } ;
239
+ Ok ( token)
240
+ }
241
+
208
242
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
209
243
/// iterator is not modified and the result is `false`.
210
244
fn try_eat_comma ( iter : & mut RefTokenTreeCursor < ' _ > ) -> bool {
211
- if let Some ( TokenTree :: Token ( token :: Token { kind : token:: Comma , .. } , _) ) = iter. look_ahead ( 0 ) {
245
+ if let Some ( TokenTree :: Token ( Token { kind : token:: Comma , .. } , _) ) = iter. look_ahead ( 0 ) {
212
246
let _ = iter. next ( ) ;
213
247
return true ;
214
248
}
@@ -218,8 +252,7 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
218
252
/// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the
219
253
/// iterator is not modified and the result is `false`.
220
254
fn try_eat_dollar ( iter : & mut RefTokenTreeCursor < ' _ > ) -> bool {
221
- if let Some ( TokenTree :: Token ( token:: Token { kind : token:: Dollar , .. } , _) ) = iter. look_ahead ( 0 )
222
- {
255
+ if let Some ( TokenTree :: Token ( Token { kind : token:: Dollar , .. } , _) ) = iter. look_ahead ( 0 ) {
223
256
let _ = iter. next ( ) ;
224
257
return true ;
225
258
}
@@ -232,8 +265,7 @@ fn eat_dollar<'psess>(
232
265
psess : & ' psess ParseSess ,
233
266
span : Span ,
234
267
) -> PResult < ' psess , ( ) > {
235
- if let Some ( TokenTree :: Token ( token:: Token { kind : token:: Dollar , .. } , _) ) = iter. look_ahead ( 0 )
236
- {
268
+ if let Some ( TokenTree :: Token ( Token { kind : token:: Dollar , .. } , _) ) = iter. look_ahead ( 0 ) {
237
269
let _ = iter. next ( ) ;
238
270
return Ok ( ( ) ) ;
239
271
}
0 commit comments