@@ -14,8 +14,8 @@ use rustc_macros::HashStable_Generic;
1414use rustc_span:: symbol:: kw;
1515use rustc_span:: symbol:: Symbol ;
1616use rustc_span:: { self , Span , DUMMY_SP } ;
17- use std:: fmt ;
18- use std:: mem;
17+ use std:: borrow :: Cow ;
18+ use std:: { fmt , mem} ;
1919
2020#[ derive( Clone , PartialEq , RustcEncodable , RustcDecodable , Hash , Debug , Copy ) ]
2121#[ derive( HashStable_Generic ) ]
@@ -328,6 +328,18 @@ impl Token {
328328 mem:: replace ( self , Token :: dummy ( ) )
329329 }
330330
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+
331343 pub fn is_op ( & self ) -> bool {
332344 match self . kind {
333345 OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | DocComment ( ..) | Ident ( ..)
@@ -345,7 +357,7 @@ impl Token {
345357
346358 /// Returns `true` if the token can appear at the start of an expression.
347359 pub fn can_begin_expr ( & self ) -> bool {
348- match self . kind {
360+ match self . uninterpolate ( ) . kind {
349361 Ident ( name, is_raw) =>
350362 ident_can_begin_expr ( name, self . span , is_raw) , // value name or keyword
351363 OpenDelim ( ..) | // tuple, array or block
@@ -363,12 +375,10 @@ impl Token {
363375 Lifetime ( ..) | // labeled loop
364376 Pound => true , // expression attributes
365377 Interpolated ( ref nt) => match * * nt {
366- NtIdent ( ident, is_raw) => ident_can_begin_expr ( ident. name , ident. span , is_raw) ,
367378 NtLiteral ( ..) |
368379 NtExpr ( ..) |
369380 NtBlock ( ..) |
370- NtPath ( ..) |
371- NtLifetime ( ..) => true ,
381+ NtPath ( ..) => true ,
372382 _ => false ,
373383 } ,
374384 _ => false ,
@@ -377,7 +387,7 @@ impl Token {
377387
378388 /// Returns `true` if the token can appear at the start of a type.
379389 pub fn can_begin_type ( & self ) -> bool {
380- match self . kind {
390+ match self . uninterpolate ( ) . kind {
381391 Ident ( name, is_raw) =>
382392 ident_can_begin_type ( name, self . span , is_raw) , // type name or keyword
383393 OpenDelim ( Paren ) | // tuple
@@ -391,8 +401,7 @@ impl Token {
391401 Lt | BinOp ( Shl ) | // associated path
392402 ModSep => true , // global path
393403 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 ,
396405 _ => false ,
397406 } ,
398407 _ => false ,
@@ -433,38 +442,47 @@ impl Token {
433442 ///
434443 /// Keep this in sync with `Lit::from_token`.
435444 pub fn can_begin_literal_or_bool ( & self ) -> bool {
436- match self . kind {
445+ match self . uninterpolate ( ) . kind {
437446 Literal ( ..) | BinOp ( Minus ) => true ,
438447 Ident ( name, false ) if name. is_bool_lit ( ) => true ,
439448 Interpolated ( ref nt) => match & * * nt {
440- NtIdent ( ident, false ) if ident. name . is_bool_lit ( ) => true ,
441449 NtExpr ( e) | NtLiteral ( e) => matches ! ( e. kind, ast:: ExprKind :: Lit ( _) ) ,
442450 _ => false ,
443451 } ,
444452 _ => false ,
445453 }
446454 }
447455
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+
448472 /// Returns an identifier if this token is an identifier.
449473 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) ) ,
456477 _ => None ,
457478 }
458479 }
459480
460481 /// Returns a lifetime identifier if this token is a lifetime.
461482 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 ) ) ,
468486 _ => None ,
469487 }
470488 }
@@ -714,6 +732,24 @@ pub enum Nonterminal {
714732#[ cfg( target_arch = "x86_64" ) ]
715733rustc_data_structures:: static_assert_size!( Nonterminal , 40 ) ;
716734
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+
717753impl PartialEq for Nonterminal {
718754 fn eq ( & self , rhs : & Self ) -> bool {
719755 match ( self , rhs) {
0 commit comments