@@ -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 ) ]
@@ -328,6 +328,18 @@ impl Token {
328
328
mem:: replace ( self , Token :: dummy ( ) )
329
329
}
330
330
331
+ /// For interpolated tokens returns a span of the fragment to which the interpolated
332
+ /// token refers, for all other tokens this is just a regular span.
333
+ /// It is particularly important to use this for identifiers and lifetimes
334
+ /// for which spans affect name resolution. This also includes edition checks
335
+ /// for edition-specific keyword identifiers.
336
+ pub fn uninterpolated_span ( & self ) -> Span {
337
+ match & self . kind {
338
+ Interpolated ( nt) => nt. span ( ) ,
339
+ _ => self . span ,
340
+ }
341
+ }
342
+
331
343
pub fn is_op ( & self ) -> bool {
332
344
match self . kind {
333
345
OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | DocComment ( ..) | Ident ( ..)
@@ -345,7 +357,7 @@ impl Token {
345
357
346
358
/// Returns `true` if the token can appear at the start of an expression.
347
359
pub fn can_begin_expr ( & self ) -> bool {
348
- match self . kind {
360
+ match self . uninterpolate ( ) . kind {
349
361
Ident ( name, is_raw) =>
350
362
ident_can_begin_expr ( name, self . span , is_raw) , // value name or keyword
351
363
OpenDelim ( ..) | // tuple, array or block
@@ -363,12 +375,10 @@ impl Token {
363
375
Lifetime ( ..) | // labeled loop
364
376
Pound => true , // expression attributes
365
377
Interpolated ( ref nt) => match * * nt {
366
- NtIdent ( ident, is_raw) => ident_can_begin_expr ( ident. name , ident. span , is_raw) ,
367
378
NtLiteral ( ..) |
368
379
NtExpr ( ..) |
369
380
NtBlock ( ..) |
370
- NtPath ( ..) |
371
- NtLifetime ( ..) => true ,
381
+ NtPath ( ..) => true ,
372
382
_ => false ,
373
383
} ,
374
384
_ => false ,
@@ -377,7 +387,7 @@ impl Token {
377
387
378
388
/// Returns `true` if the token can appear at the start of a type.
379
389
pub fn can_begin_type ( & self ) -> bool {
380
- match self . kind {
390
+ match self . uninterpolate ( ) . kind {
381
391
Ident ( name, is_raw) =>
382
392
ident_can_begin_type ( name, self . span , is_raw) , // type name or keyword
383
393
OpenDelim ( Paren ) | // tuple
@@ -391,8 +401,7 @@ impl Token {
391
401
Lt | BinOp ( Shl ) | // associated path
392
402
ModSep => true , // global path
393
403
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 ,
404
+ NtTy ( ..) | NtPath ( ..) => true ,
396
405
_ => false ,
397
406
} ,
398
407
_ => false ,
@@ -433,38 +442,47 @@ impl Token {
433
442
///
434
443
/// Keep this in sync with `Lit::from_token`.
435
444
pub fn can_begin_literal_or_bool ( & self ) -> bool {
436
- match self . kind {
445
+ match self . uninterpolate ( ) . kind {
437
446
Literal ( ..) | BinOp ( Minus ) => true ,
438
447
Ident ( name, false ) if name. is_bool_lit ( ) => true ,
439
448
Interpolated ( ref nt) => match & * * nt {
440
- NtIdent ( ident, false ) if ident. name . is_bool_lit ( ) => true ,
441
449
NtExpr ( e) | NtLiteral ( e) => matches ! ( e. kind, ast:: ExprKind :: Lit ( _) ) ,
442
450
_ => false ,
443
451
} ,
444
452
_ => false ,
445
453
}
446
454
}
447
455
456
+ // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
457
+ // into the regular identifier or lifetime token it refers to,
458
+ // otherwise returns the original token.
459
+ pub fn uninterpolate ( & self ) -> Cow < ' _ , Token > {
460
+ match & self . kind {
461
+ Interpolated ( nt) => match * * nt {
462
+ NtIdent ( ident, is_raw) => {
463
+ Cow :: Owned ( Token :: new ( Ident ( ident. name , is_raw) , ident. span ) )
464
+ }
465
+ NtLifetime ( ident) => Cow :: Owned ( Token :: new ( Lifetime ( ident. name ) , ident. span ) ) ,
466
+ _ => Cow :: Borrowed ( self ) ,
467
+ } ,
468
+ _ => Cow :: Borrowed ( self ) ,
469
+ }
470
+ }
471
+
448
472
/// Returns an identifier if this token is an identifier.
449
473
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
- } ,
474
+ let token = self . uninterpolate ( ) ;
475
+ match token. kind {
476
+ Ident ( name, is_raw) => Some ( ( ast:: Ident :: new ( name, token. span ) , is_raw) ) ,
456
477
_ => None ,
457
478
}
458
479
}
459
480
460
481
/// Returns a lifetime identifier if this token is a lifetime.
461
482
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
- } ,
483
+ let token = self . uninterpolate ( ) ;
484
+ match token. kind {
485
+ Lifetime ( name) => Some ( ast:: Ident :: new ( name, token. span ) ) ,
468
486
_ => None ,
469
487
}
470
488
}
@@ -714,6 +732,24 @@ pub enum Nonterminal {
714
732
#[ cfg( target_arch = "x86_64" ) ]
715
733
rustc_data_structures:: static_assert_size!( Nonterminal , 40 ) ;
716
734
735
+ impl Nonterminal {
736
+ fn span ( & self ) -> Span {
737
+ match self {
738
+ NtItem ( item) => item. span ,
739
+ NtBlock ( block) => block. span ,
740
+ NtStmt ( stmt) => stmt. span ,
741
+ NtPat ( pat) => pat. span ,
742
+ NtExpr ( expr) | NtLiteral ( expr) => expr. span ,
743
+ NtTy ( ty) => ty. span ,
744
+ NtIdent ( ident, _) | NtLifetime ( ident) => ident. span ,
745
+ NtMeta ( attr_item) => attr_item. span ( ) ,
746
+ NtPath ( path) => path. span ,
747
+ NtVis ( vis) => vis. span ,
748
+ NtTT ( tt) => tt. span ( ) ,
749
+ }
750
+ }
751
+ }
752
+
717
753
impl PartialEq for Nonterminal {
718
754
fn eq ( & self , rhs : & Self ) -> bool {
719
755
match ( self , rhs) {
0 commit comments