@@ -2533,10 +2533,16 @@ impl fmt::Debug for Ident {
25332533/// except that AST identifiers don't keep the rawness flag, so we have to guess it.
25342534impl fmt:: Display for Ident {
25352535 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
2536- fmt:: Display :: fmt ( & IdentPrinter :: new ( self . name , self . is_raw_guess ( ) , None ) , f)
2536+ fmt:: Display :: fmt ( & IdentPrinter :: new ( self . name , self . guess_print_mode ( ) , None ) , f)
25372537 }
25382538}
25392539
2540+ pub enum IdentPrintMode {
2541+ Normal ,
2542+ RawIdent ,
2543+ RawLifetime ,
2544+ }
2545+
25402546/// The most general type to print identifiers.
25412547///
25422548/// AST pretty-printer is used as a fallback for turning AST structures into token streams for
@@ -2552,40 +2558,59 @@ impl fmt::Display for Ident {
25522558/// done for a token stream or a single token.
25532559pub struct IdentPrinter {
25542560 symbol : Symbol ,
2555- is_raw : bool ,
2561+ mode : IdentPrintMode ,
25562562 /// Span used for retrieving the crate name to which `$crate` refers to,
25572563 /// if this field is `None` then the `$crate` conversion doesn't happen.
25582564 convert_dollar_crate : Option < Span > ,
25592565}
25602566
25612567impl IdentPrinter {
25622568 /// The most general `IdentPrinter` constructor. Do not use this.
2563- pub fn new ( symbol : Symbol , is_raw : bool , convert_dollar_crate : Option < Span > ) -> IdentPrinter {
2564- IdentPrinter { symbol, is_raw, convert_dollar_crate }
2569+ pub fn new (
2570+ symbol : Symbol ,
2571+ mode : IdentPrintMode ,
2572+ convert_dollar_crate : Option < Span > ,
2573+ ) -> IdentPrinter {
2574+ IdentPrinter { symbol, mode, convert_dollar_crate }
25652575 }
25662576
25672577 /// This implementation is supposed to be used when printing identifiers
25682578 /// as a part of pretty-printing for larger AST pieces.
25692579 /// Do not use this either.
2570- pub fn for_ast_ident ( ident : Ident , is_raw : bool ) -> IdentPrinter {
2571- IdentPrinter :: new ( ident. name , is_raw , Some ( ident. span ) )
2580+ pub fn for_ast_ident ( ident : Ident , mode : IdentPrintMode ) -> IdentPrinter {
2581+ IdentPrinter :: new ( ident. name , mode , Some ( ident. span ) )
25722582 }
25732583}
25742584
25752585impl fmt:: Display for IdentPrinter {
25762586 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
2577- if self . is_raw {
2578- f. write_str ( "r#" ) ?;
2579- } else if self . symbol == kw:: DollarCrate {
2580- if let Some ( span) = self . convert_dollar_crate {
2587+ let s = match self . mode {
2588+ IdentPrintMode :: Normal
2589+ if self . symbol == kw:: DollarCrate
2590+ && let Some ( span) = self . convert_dollar_crate =>
2591+ {
25812592 let converted = span. ctxt ( ) . dollar_crate_name ( ) ;
25822593 if !converted. is_path_segment_keyword ( ) {
25832594 f. write_str ( "::" ) ?;
25842595 }
2585- return fmt :: Display :: fmt ( & converted, f ) ;
2596+ converted
25862597 }
2587- }
2588- fmt:: Display :: fmt ( & self . symbol , f)
2598+ IdentPrintMode :: Normal => self . symbol ,
2599+ IdentPrintMode :: RawIdent => {
2600+ f. write_str ( "r#" ) ?;
2601+ self . symbol
2602+ }
2603+ IdentPrintMode :: RawLifetime => {
2604+ f. write_str ( "'r#" ) ?;
2605+ let s = self
2606+ . symbol
2607+ . as_str ( )
2608+ . strip_prefix ( "'" )
2609+ . expect ( "only lifetime idents should be passed with RawLifetime mode" ) ;
2610+ Symbol :: intern ( s)
2611+ }
2612+ } ;
2613+ s. fmt ( f)
25892614 }
25902615}
25912616
@@ -3020,6 +3045,29 @@ impl Ident {
30203045 self . name . can_be_raw ( ) && self . is_reserved ( )
30213046 }
30223047
3048+ /// Given the name of a lifetime without the first quote (`'`),
3049+ /// returns whether the lifetime name is reserved (therefore invalid)
3050+ pub fn is_reserved_lifetime ( self ) -> bool {
3051+ self . is_reserved ( ) && ![ kw:: Underscore , kw:: Static ] . contains ( & self . name )
3052+ }
3053+
3054+ pub fn is_raw_lifetime_guess ( self ) -> bool {
3055+ let name_without_apostrophe = self . without_first_quote ( ) ;
3056+ name_without_apostrophe. name != self . name
3057+ && name_without_apostrophe. name . can_be_raw ( )
3058+ && name_without_apostrophe. is_reserved_lifetime ( )
3059+ }
3060+
3061+ pub fn guess_print_mode ( self ) -> IdentPrintMode {
3062+ if self . is_raw_lifetime_guess ( ) {
3063+ IdentPrintMode :: RawLifetime
3064+ } else if self . is_raw_guess ( ) {
3065+ IdentPrintMode :: RawIdent
3066+ } else {
3067+ IdentPrintMode :: Normal
3068+ }
3069+ }
3070+
30233071 /// Whether this would be the identifier for a tuple field like `self.0`, as
30243072 /// opposed to a named field like `self.thing`.
30253073 pub fn is_numeric ( self ) -> bool {
0 commit comments