@@ -14,8 +14,8 @@ use rustc_macros::HashStable_Generic;
14
14
use rustc_span:: symbol:: kw;
15
15
use rustc_span:: symbol:: Symbol ;
16
16
use rustc_span:: { self , Span , DUMMY_SP } ;
17
- use std:: fmt ;
18
- use std:: mem;
17
+ use std:: borrow :: Cow ;
18
+ use std:: { fmt , mem} ;
19
19
20
20
#[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Hash , Debug , Copy ) ]
21
21
#[ derive( HashStable_Generic ) ]
@@ -225,8 +225,15 @@ pub enum TokenKind {
225
225
/* Literals */
226
226
Literal ( Lit ) ,
227
227
228
- /* Name components */
228
+ /// Identifier token.
229
+ /// Do not forget about `NtIdent` when you want to match on identifiers.
230
+ /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
231
+ /// treat regular and interpolated identifiers in the same way.
229
232
Ident ( ast:: Name , /* is_raw */ bool ) ,
233
+ /// Lifetime identifier token.
234
+ /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
235
+ /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
236
+ /// treat regular and interpolated lifetime identifiers in the same way.
230
237
Lifetime ( ast:: Name ) ,
231
238
232
239
Interpolated ( Lrc < Nonterminal > ) ,
@@ -328,6 +335,19 @@ impl Token {
328
335
mem:: replace ( self , Token :: dummy ( ) )
329
336
}
330
337
338
+ /// For interpolated tokens, returns a span of the fragment to which the interpolated
339
+ /// token refers. For all other tokens this is just a regular span.
340
+ /// It is particularly important to use this for identifiers and lifetimes
341
+ /// for which spans affect name resolution and edition checks.
342
+ /// Note that keywords are also identifiers, so they should use this
343
+ /// if they keep spans or perform edition checks.
344
+ pub fn uninterpolated_span ( & self ) -> Span {
345
+ match & self . kind {
346
+ Interpolated ( nt) => nt. span ( ) ,
347
+ _ => self . span ,
348
+ }
349
+ }
350
+
331
351
pub fn is_op ( & self ) -> bool {
332
352
match self . kind {
333
353
OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | DocComment ( ..) | Ident ( ..)
@@ -345,7 +365,7 @@ impl Token {
345
365
346
366
/// Returns `true` if the token can appear at the start of an expression.
347
367
pub fn can_begin_expr ( & self ) -> bool {
348
- match self . kind {
368
+ match self . uninterpolate ( ) . kind {
349
369
Ident ( name, is_raw) =>
350
370
ident_can_begin_expr ( name, self . span , is_raw) , // value name or keyword
351
371
OpenDelim ( ..) | // tuple, array or block
@@ -363,12 +383,10 @@ impl Token {
363
383
Lifetime ( ..) | // labeled loop
364
384
Pound => true , // expression attributes
365
385
Interpolated ( ref nt) => match * * nt {
366
- NtIdent ( ident, is_raw) => ident_can_begin_expr ( ident. name , ident. span , is_raw) ,
367
386
NtLiteral ( ..) |
368
387
NtExpr ( ..) |
369
388
NtBlock ( ..) |
370
- NtPath ( ..) |
371
- NtLifetime ( ..) => true ,
389
+ NtPath ( ..) => true ,
372
390
_ => false ,
373
391
} ,
374
392
_ => false ,
@@ -377,7 +395,7 @@ impl Token {
377
395
378
396
/// Returns `true` if the token can appear at the start of a type.
379
397
pub fn can_begin_type ( & self ) -> bool {
380
- match self . kind {
398
+ match self . uninterpolate ( ) . kind {
381
399
Ident ( name, is_raw) =>
382
400
ident_can_begin_type ( name, self . span , is_raw) , // type name or keyword
383
401
OpenDelim ( Paren ) | // tuple
@@ -391,8 +409,7 @@ impl Token {
391
409
Lt | BinOp ( Shl ) | // associated path
392
410
ModSep => true , // global path
393
411
Interpolated ( ref nt) => match * * nt {
394
- NtIdent ( ident, is_raw) => ident_can_begin_type ( ident. name , ident. span , is_raw) ,
395
- NtTy ( ..) | NtPath ( ..) | NtLifetime ( ..) => true ,
412
+ NtTy ( ..) | NtPath ( ..) => true ,
396
413
_ => false ,
397
414
} ,
398
415
_ => false ,
@@ -433,38 +450,48 @@ impl Token {
433
450
///
434
451
/// Keep this in sync with `Lit::from_token`.
435
452
pub fn can_begin_literal_or_bool ( & self ) -> bool {
436
- match self . kind {
453
+ match self . uninterpolate ( ) . kind {
437
454
Literal ( ..) | BinOp ( Minus ) => true ,
438
455
Ident ( name, false ) if name. is_bool_lit ( ) => true ,
439
456
Interpolated ( ref nt) => match & * * nt {
440
- NtIdent ( ident, false ) if ident. name . is_bool_lit ( ) => true ,
441
457
NtExpr ( e) | NtLiteral ( e) => matches ! ( e. kind, ast:: ExprKind :: Lit ( _) ) ,
442
458
_ => false ,
443
459
} ,
444
460
_ => false ,
445
461
}
446
462
}
447
463
464
+ // A convenience function for matching on identifiers during parsing.
465
+ // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
466
+ // into the regular identifier or lifetime token it refers to,
467
+ // otherwise returns the original token.
468
+ pub fn uninterpolate ( & self ) -> Cow < ' _ , Token > {
469
+ match & self . kind {
470
+ Interpolated ( nt) => match * * nt {
471
+ NtIdent ( ident, is_raw) => {
472
+ Cow :: Owned ( Token :: new ( Ident ( ident. name , is_raw) , ident. span ) )
473
+ }
474
+ NtLifetime ( ident) => Cow :: Owned ( Token :: new ( Lifetime ( ident. name ) , ident. span ) ) ,
475
+ _ => Cow :: Borrowed ( self ) ,
476
+ } ,
477
+ _ => Cow :: Borrowed ( self ) ,
478
+ }
479
+ }
480
+
448
481
/// Returns an identifier if this token is an identifier.
449
482
pub fn ident ( & self ) -> Option < ( ast:: Ident , /* is_raw */ bool ) > {
450
- match self . kind {
451
- Ident ( name, is_raw) => Some ( ( ast:: Ident :: new ( name, self . span ) , is_raw) ) ,
452
- Interpolated ( ref nt) => match * * nt {
453
- NtIdent ( ident, is_raw) => Some ( ( ident, is_raw) ) ,
454
- _ => None ,
455
- } ,
483
+ let token = self . uninterpolate ( ) ;
484
+ match token. kind {
485
+ Ident ( name, is_raw) => Some ( ( ast:: Ident :: new ( name, token. span ) , is_raw) ) ,
456
486
_ => None ,
457
487
}
458
488
}
459
489
460
490
/// Returns a lifetime identifier if this token is a lifetime.
461
491
pub fn lifetime ( & self ) -> Option < ast:: Ident > {
462
- match self . kind {
463
- Lifetime ( name) => Some ( ast:: Ident :: new ( name, self . span ) ) ,
464
- Interpolated ( ref nt) => match * * nt {
465
- NtLifetime ( ident) => Some ( ident) ,
466
- _ => None ,
467
- } ,
492
+ let token = self . uninterpolate ( ) ;
493
+ match token. kind {
494
+ Lifetime ( name) => Some ( ast:: Ident :: new ( name, token. span ) ) ,
468
495
_ => None ,
469
496
}
470
497
}
@@ -714,6 +741,24 @@ pub enum Nonterminal {
714
741
#[ cfg( target_arch = "x86_64" ) ]
715
742
rustc_data_structures:: static_assert_size!( Nonterminal , 40 ) ;
716
743
744
+ impl Nonterminal {
745
+ fn span ( & self ) -> Span {
746
+ match self {
747
+ NtItem ( item) => item. span ,
748
+ NtBlock ( block) => block. span ,
749
+ NtStmt ( stmt) => stmt. span ,
750
+ NtPat ( pat) => pat. span ,
751
+ NtExpr ( expr) | NtLiteral ( expr) => expr. span ,
752
+ NtTy ( ty) => ty. span ,
753
+ NtIdent ( ident, _) | NtLifetime ( ident) => ident. span ,
754
+ NtMeta ( attr_item) => attr_item. span ( ) ,
755
+ NtPath ( path) => path. span ,
756
+ NtVis ( vis) => vis. span ,
757
+ NtTT ( tt) => tt. span ( ) ,
758
+ }
759
+ }
760
+ }
761
+
717
762
impl PartialEq for Nonterminal {
718
763
fn eq ( & self , rhs : & Self ) -> bool {
719
764
match ( self , rhs) {
0 commit comments