@@ -107,7 +107,9 @@ impl Lit {
107107 /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
108108 pub fn from_token ( token : & Token ) -> Option < Lit > {
109109 match token. uninterpolate ( ) . kind {
110- Ident ( name, false ) if name. is_bool_lit ( ) => Some ( Lit :: new ( Bool , name, None ) ) ,
110+ Ident ( name, IdentKind :: Default ) if name. is_bool_lit ( ) => {
111+ Some ( Lit :: new ( Bool , name, None ) )
112+ }
111113 Literal ( token_lit) => Some ( token_lit) ,
112114 Interpolated ( ref nt)
113115 if let NtExpr ( expr) | NtLiteral ( expr) = & nt. 0
@@ -183,8 +185,8 @@ impl LitKind {
183185 }
184186}
185187
186- pub fn ident_can_begin_expr ( name : Symbol , span : Span , is_raw : bool ) -> bool {
187- let ident_token = Token :: new ( Ident ( name, is_raw ) , span) ;
188+ pub fn ident_can_begin_expr ( name : Symbol , span : Span , kind : IdentKind ) -> bool {
189+ let ident_token = Token :: new ( Ident ( name, kind ) , span) ;
188190
189191 !ident_token. is_reserved_ident ( )
190192 || ident_token. is_path_segment_keyword ( )
@@ -212,15 +214,37 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
212214 kw:: Static ,
213215 ]
214216 . contains ( & name)
217+ || kind == IdentKind :: Keyword
215218}
216219
217- fn ident_can_begin_type ( name : Symbol , span : Span , is_raw : bool ) -> bool {
218- let ident_token = Token :: new ( Ident ( name, is_raw ) , span) ;
220+ fn ident_can_begin_type ( name : Symbol , span : Span , kind : IdentKind ) -> bool {
221+ let ident_token = Token :: new ( Ident ( name, kind ) , span) ;
219222
220223 !ident_token. is_reserved_ident ( )
221224 || ident_token. is_path_segment_keyword ( )
222225 || [ kw:: Underscore , kw:: For , kw:: Impl , kw:: Fn , kw:: Unsafe , kw:: Extern , kw:: Typeof , kw:: Dyn ]
223226 . contains ( & name)
227+ || kind == IdentKind :: Keyword
228+ }
229+
230+ #[ derive( Clone , Copy , PartialEq , Eq , Debug , HashStable_Generic , Encodable , Decodable ) ]
231+ pub enum IdentKind {
232+ /// The usual identifiers (or, depending on the context, keywords): `v`, `union`, `await`, `loop`.
233+ Default ,
234+ /// Raw identifiers: `r#just_an_ident`, `r#loop`.
235+ Raw ,
236+ /// Forced keywords: `k#break`, `k#await`, `k#some_new_experimental_keyword`.
237+ Keyword ,
238+ }
239+
240+ impl IdentKind {
241+ pub fn prefix ( self ) -> Option < & ' static str > {
242+ match self {
243+ IdentKind :: Default => None ,
244+ IdentKind :: Raw => Some ( "r#" ) ,
245+ IdentKind :: Keyword => Some ( "k#" ) ,
246+ }
247+ }
224248}
225249
226250// SAFETY: due to the `Clone` impl below, all fields of all variants other than
@@ -298,10 +322,7 @@ pub enum TokenKind {
298322 /// Do not forget about `NtIdent` when you want to match on identifiers.
299323 /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
300324 /// treat regular and interpolated identifiers in the same way.
301- Ident ( Symbol , /* is_raw */ bool ) ,
302-
303- /// A `k#ident` keyword
304- Keyword ( Symbol ) ,
325+ Ident ( Symbol , IdentKind ) ,
305326
306327 /// Lifetime identifier token.
307328 /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
@@ -415,7 +436,13 @@ impl Token {
415436
416437 /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary.
417438 pub fn from_ast_ident ( ident : Ident ) -> Self {
418- Token :: new ( Ident ( ident. name , ident. is_raw_guess ( ) ) , ident. span )
439+ Token :: new (
440+ Ident (
441+ ident. name ,
442+ if ident. is_raw_guess ( ) { IdentKind :: Raw } else { IdentKind :: Default } ,
443+ ) ,
444+ ident. span ,
445+ )
419446 }
420447
421448 /// For interpolated tokens, returns a span of the fragment to which the interpolated
@@ -442,7 +469,7 @@ impl Token {
442469 | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true ,
443470
444471 OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | DocComment ( ..) | Ident ( ..)
445- | Keyword ( .. ) | Lifetime ( ..) | Interpolated ( ..) | Eof => false ,
472+ | Lifetime ( ..) | Interpolated ( ..) | Eof => false ,
446473 }
447474 }
448475
@@ -580,7 +607,7 @@ impl Token {
580607 pub fn can_begin_literal_maybe_minus ( & self ) -> bool {
581608 match self . uninterpolate ( ) . kind {
582609 Literal ( ..) | BinOp ( Minus ) => true ,
583- Ident ( name, false ) if name. is_bool_lit ( ) => true ,
610+ Ident ( name, IdentKind :: Default ) if name. is_bool_lit ( ) => true ,
584611 Interpolated ( ref nt) => match & nt. 0 {
585612 NtLiteral ( _) => true ,
586613 NtExpr ( e) => match & e. kind {
@@ -615,10 +642,10 @@ impl Token {
615642
616643 /// Returns an identifier if this token is an identifier.
617644 #[ inline]
618- pub fn ident ( & self ) -> Option < ( Ident , /* is_raw */ bool ) > {
645+ pub fn ident ( & self ) -> Option < ( Ident , IdentKind ) > {
619646 // We avoid using `Token::uninterpolate` here because it's slow.
620647 match & self . kind {
621- & Ident ( name, is_raw ) => Some ( ( Ident :: new ( name, self . span ) , is_raw ) ) ,
648+ & Ident ( name, kind ) => Some ( ( Ident :: new ( name, self . span ) , kind ) ) ,
622649 Interpolated ( nt) => match & nt. 0 {
623650 NtIdent ( ident, is_raw) => Some ( ( * ident, * is_raw) ) ,
624651 _ => None ,
@@ -711,46 +738,46 @@ impl Token {
711738
712739 /// Returns `true` if the token is a given keyword, `kw`.
713740 pub fn is_keyword ( & self , kw : Symbol ) -> bool {
714- self . is_non_raw_ident_where ( |id| id. name == kw)
741+ self . is_keywordable_ident_where ( |id| id. name == kw)
715742 }
716743
717744 /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this token is an identifier equal to `kw` ignoring the case.
718745 pub fn is_keyword_case ( & self , kw : Symbol , case : Case ) -> bool {
719746 self . is_keyword ( kw)
720747 || ( case == Case :: Insensitive
721- && self . is_non_raw_ident_where ( |id| {
748+ && self . is_keywordable_ident_where ( |id| {
722749 id. name . as_str ( ) . to_lowercase ( ) == kw. as_str ( ) . to_lowercase ( )
723750 } ) )
724751 }
725752
726753 pub fn is_path_segment_keyword ( & self ) -> bool {
727- self . is_non_raw_ident_where ( Ident :: is_path_segment_keyword)
754+ self . is_keywordable_ident_where ( Ident :: is_path_segment_keyword)
728755 }
729756
730757 /// Returns true for reserved identifiers used internally for elided lifetimes,
731758 /// unnamed method parameters, crate root module, error recovery etc.
732759 pub fn is_special_ident ( & self ) -> bool {
733- self . is_non_raw_ident_where ( Ident :: is_special)
760+ self . is_keywordable_ident_where ( Ident :: is_special)
734761 }
735762
736763 /// Returns `true` if the token is a keyword used in the language.
737764 pub fn is_used_keyword ( & self ) -> bool {
738- self . is_non_raw_ident_where ( Ident :: is_used_keyword)
765+ self . is_keywordable_ident_where ( Ident :: is_used_keyword)
739766 }
740767
741768 /// Returns `true` if the token is a keyword reserved for possible future use.
742769 pub fn is_unused_keyword ( & self ) -> bool {
743- self . is_non_raw_ident_where ( Ident :: is_unused_keyword)
770+ self . is_keywordable_ident_where ( Ident :: is_unused_keyword)
744771 }
745772
746773 /// Returns `true` if the token is either a special identifier or a keyword.
747774 pub fn is_reserved_ident ( & self ) -> bool {
748- self . is_non_raw_ident_where ( Ident :: is_reserved)
775+ self . is_keywordable_ident_where ( Ident :: is_reserved)
749776 }
750777
751778 /// Returns `true` if the token is the identifier `true` or `false`.
752779 pub fn is_bool_lit ( & self ) -> bool {
753- self . is_non_raw_ident_where ( |id| id. name . is_bool_lit ( ) )
780+ self . is_keywordable_ident_where ( |id| id. name . is_bool_lit ( ) )
754781 }
755782
756783 pub fn is_numeric_lit ( & self ) -> bool {
@@ -766,9 +793,9 @@ impl Token {
766793 }
767794
768795 /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
769- pub fn is_non_raw_ident_where ( & self , pred : impl FnOnce ( Ident ) -> bool ) -> bool {
796+ pub fn is_keywordable_ident_where ( & self , pred : impl FnOnce ( Ident ) -> bool ) -> bool {
770797 match self . ident ( ) {
771- Some ( ( id, false ) ) => pred ( id) ,
798+ Some ( ( id, IdentKind :: Default | IdentKind :: Keyword ) ) => pred ( id) ,
772799 _ => false ,
773800 }
774801 }
@@ -819,13 +846,13 @@ impl Token {
819846 _ => return None ,
820847 } ,
821848 SingleQuote => match joint. kind {
822- Ident ( name, false ) => Lifetime ( Symbol :: intern ( & format ! ( "'{name}" ) ) ) ,
849+ Ident ( name, IdentKind :: Default ) => Lifetime ( Symbol :: intern ( & format ! ( "'{name}" ) ) ) ,
823850 _ => return None ,
824851 } ,
825852
826853 Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq ( ..) | At | DotDotDot
827854 | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
828- | Question | OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | Ident ( ..) | Keyword ( .. )
855+ | Question | OpenDelim ( ..) | CloseDelim ( ..) | Literal ( ..) | Ident ( ..)
829856 | Lifetime ( ..) | Interpolated ( ..) | DocComment ( ..) | Eof => return None ,
830857 } ;
831858
@@ -849,7 +876,7 @@ pub enum Nonterminal {
849876 NtPat ( P < ast:: Pat > ) ,
850877 NtExpr ( P < ast:: Expr > ) ,
851878 NtTy ( P < ast:: Ty > ) ,
852- NtIdent ( Ident , /* is_raw */ bool ) ,
879+ NtIdent ( Ident , IdentKind ) ,
853880 NtLifetime ( Ident ) ,
854881 NtLiteral ( P < ast:: Expr > ) ,
855882 /// Stuff inside brackets for attributes
0 commit comments