@@ -18,7 +18,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
1818
1919use rustc_target:: spec:: abi:: { self , Abi } ;
2020use syntax_pos:: { self , BytePos } ;
21- use syntax_pos:: { DUMMY_SP , FileName } ;
21+ use syntax_pos:: { DUMMY_SP , FileName , Span } ;
2222
2323use std:: borrow:: Cow ;
2424use std:: io:: Read ;
@@ -181,7 +181,46 @@ pub fn literal_to_string(lit: token::Lit) -> String {
181181 out
182182}
183183
184+ fn ident_to_string ( ident : ast:: Ident , is_raw : bool ) -> String {
185+ ident_to_string_ext ( ident. name , is_raw, Some ( ident. span ) )
186+ }
187+
188+ // AST pretty-printer is used as a fallback for turning AST structures into token streams for
189+ // proc macros. Additionally, proc macros may stringify their input and expect it survive the
190+ // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
191+ // So we need to somehow pretty-print `$crate` in a way preserving at least some of its
192+ // hygiene data, most importantly name of the crate it refers to.
193+ // As a result we print `$crate` as `crate` if it refers to the local crate
194+ // and as `::other_crate_name` if it refers to some other crate.
195+ // Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
196+ // but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
197+ // so we should not perform this lossy conversion if the top level call to the pretty-printer was
198+ // done for a token stream or a single token.
199+ fn ident_to_string_ext (
200+ name : ast:: Name , is_raw : bool , convert_dollar_crate : Option < Span >
201+ ) -> String {
202+ if is_raw {
203+ format ! ( "r#{}" , name)
204+ } else {
205+ if name == kw:: DollarCrate {
206+ if let Some ( span) = convert_dollar_crate {
207+ let converted = span. ctxt ( ) . dollar_crate_name ( ) ;
208+ return if converted. is_path_segment_keyword ( ) {
209+ converted. to_string ( )
210+ } else {
211+ format ! ( "::{}" , converted)
212+ }
213+ }
214+ }
215+ name. to_string ( )
216+ }
217+ }
218+
184219pub fn token_kind_to_string ( tok : & TokenKind ) -> String {
220+ token_kind_to_string_ext ( tok, None )
221+ }
222+
223+ fn token_kind_to_string_ext ( tok : & TokenKind , convert_dollar_crate : Option < Span > ) -> String {
185224 match * tok {
186225 token:: Eq => "=" . to_string ( ) ,
187226 token:: Lt => "<" . to_string ( ) ,
@@ -227,8 +266,7 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
227266 token:: Literal ( lit) => literal_to_string ( lit) ,
228267
229268 /* Name components */
230- token:: Ident ( s, false ) => s. to_string ( ) ,
231- token:: Ident ( s, true ) => format ! ( "r#{}" , s) ,
269+ token:: Ident ( s, is_raw) => ident_to_string_ext ( s, is_raw, convert_dollar_crate) ,
232270 token:: Lifetime ( s) => s. to_string ( ) ,
233271
234272 /* Other */
@@ -243,7 +281,12 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
243281}
244282
245283pub fn token_to_string ( token : & Token ) -> String {
246- token_kind_to_string ( & token. kind )
284+ token_to_string_ext ( token, false )
285+ }
286+
287+ fn token_to_string_ext ( token : & Token , convert_dollar_crate : bool ) -> String {
288+ let convert_dollar_crate = if convert_dollar_crate { Some ( token. span ) } else { None } ;
289+ token_kind_to_string_ext ( & token. kind , convert_dollar_crate)
247290}
248291
249292crate fn nonterminal_to_string ( nt : & Nonterminal ) -> String {
@@ -256,9 +299,8 @@ crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
256299 token:: NtBlock ( ref e) => block_to_string ( e) ,
257300 token:: NtStmt ( ref e) => stmt_to_string ( e) ,
258301 token:: NtPat ( ref e) => pat_to_string ( e) ,
259- token:: NtIdent ( e, false ) => ident_to_string ( e) ,
260- token:: NtIdent ( e, true ) => format ! ( "r#{}" , ident_to_string( e) ) ,
261- token:: NtLifetime ( e) => ident_to_string ( e) ,
302+ token:: NtIdent ( e, is_raw) => ident_to_string ( e, is_raw) ,
303+ token:: NtLifetime ( e) => e. to_string ( ) ,
262304 token:: NtLiteral ( ref e) => expr_to_string ( e) ,
263305 token:: NtTT ( ref tree) => tt_to_string ( tree. clone ( ) ) ,
264306 token:: NtImplItem ( ref e) => impl_item_to_string ( e) ,
@@ -293,15 +335,15 @@ pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
293335}
294336
295337pub fn tt_to_string ( tt : tokenstream:: TokenTree ) -> String {
296- to_string ( |s| s. print_tt ( tt) )
338+ to_string ( |s| s. print_tt ( tt, false ) )
297339}
298340
299341pub fn tts_to_string ( tts : & [ tokenstream:: TokenTree ] ) -> String {
300- to_string ( |s| s . print_tts ( tts. iter ( ) . cloned ( ) . collect ( ) ) )
342+ tokens_to_string ( tts. iter ( ) . cloned ( ) . collect ( ) )
301343}
302344
303345pub fn tokens_to_string ( tokens : TokenStream ) -> String {
304- to_string ( |s| s. print_tts ( tokens) )
346+ to_string ( |s| s. print_tts_ext ( tokens, false ) )
305347}
306348
307349pub fn stmt_to_string ( stmt : & ast:: Stmt ) -> String {
@@ -344,10 +386,6 @@ pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
344386 to_string ( |s| s. print_path_segment ( p, false ) )
345387}
346388
347- pub fn ident_to_string ( id : ast:: Ident ) -> String {
348- to_string ( |s| s. print_ident ( id) )
349- }
350-
351389pub fn vis_to_string ( v : & ast:: Visibility ) -> String {
352390 to_string ( |s| s. print_visibility ( v) )
353391}
@@ -629,11 +667,7 @@ pub trait PrintState<'a> {
629667 self . writer ( ) . word ( "::" ) ;
630668 }
631669 if segment. ident . name != kw:: PathRoot {
632- if segment. ident . name == kw:: DollarCrate {
633- self . print_dollar_crate ( segment. ident ) ;
634- } else {
635- self . writer ( ) . word ( segment. ident . as_str ( ) . to_string ( ) ) ;
636- }
670+ self . writer ( ) . word ( ident_to_string ( segment. ident , segment. ident . is_raw_guess ( ) ) ) ;
637671 }
638672 }
639673 }
@@ -707,10 +741,10 @@ pub trait PrintState<'a> {
707741 /// appropriate macro, transcribe back into the grammar we just parsed from,
708742 /// and then pretty-print the resulting AST nodes (so, e.g., we print
709743 /// expression arguments as expressions). It can be done! I think.
710- fn print_tt ( & mut self , tt : tokenstream:: TokenTree ) {
744+ fn print_tt ( & mut self , tt : tokenstream:: TokenTree , convert_dollar_crate : bool ) {
711745 match tt {
712746 TokenTree :: Token ( ref token) => {
713- self . writer ( ) . word ( token_to_string ( & token) ) ;
747+ self . writer ( ) . word ( token_to_string_ext ( & token, convert_dollar_crate ) ) ;
714748 match token. kind {
715749 token:: DocComment ( ..) => {
716750 self . writer ( ) . hardbreak ( )
@@ -729,12 +763,16 @@ pub trait PrintState<'a> {
729763 }
730764
731765 fn print_tts ( & mut self , tts : tokenstream:: TokenStream ) {
766+ self . print_tts_ext ( tts, true )
767+ }
768+
769+ fn print_tts_ext ( & mut self , tts : tokenstream:: TokenStream , convert_dollar_crate : bool ) {
732770 self . ibox ( 0 ) ;
733771 for ( i, tt) in tts. into_trees ( ) . enumerate ( ) {
734772 if i != 0 {
735773 self . writer ( ) . space ( ) ;
736774 }
737- self . print_tt ( tt) ;
775+ self . print_tt ( tt, convert_dollar_crate ) ;
738776 }
739777 self . end ( ) ;
740778 }
@@ -744,21 +782,6 @@ pub trait PrintState<'a> {
744782 }
745783
746784 fn nbsp ( & mut self ) { self . writer ( ) . word ( " " ) }
747-
748- // AST pretty-printer is used as a fallback for turning AST structures into token streams for
749- // proc macros. Additionally, proc macros may stringify their input and expect it survive the
750- // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
751- // So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of
752- // its hygiene data, most importantly name of the crate it refers to.
753- // As a result we print `$crate` as `crate` if it refers to the local crate
754- // and as `::other_crate_name` if it refers to some other crate.
755- fn print_dollar_crate ( & mut self , ident : ast:: Ident ) {
756- let name = ident. span . ctxt ( ) . dollar_crate_name ( ) ;
757- if !ast:: Ident :: with_empty_ctxt ( name) . is_path_segment_keyword ( ) {
758- self . writer ( ) . word ( "::" ) ;
759- }
760- self . writer ( ) . word ( name. as_str ( ) . to_string ( ) )
761- }
762785}
763786
764787impl < ' a > PrintState < ' a > for State < ' a > {
@@ -2287,11 +2310,7 @@ impl<'a> State<'a> {
22872310 }
22882311
22892312 crate fn print_ident ( & mut self , ident : ast:: Ident ) {
2290- if ident. is_raw_guess ( ) {
2291- self . s . word ( format ! ( "r#{}" , ident) ) ;
2292- } else {
2293- self . s . word ( ident. as_str ( ) . to_string ( ) ) ;
2294- }
2313+ self . s . word ( ident_to_string ( ident, ident. is_raw_guess ( ) ) ) ;
22952314 self . ann . post ( self , AnnNode :: Ident ( & ident) )
22962315 }
22972316
@@ -2322,11 +2341,7 @@ impl<'a> State<'a> {
23222341 segment : & ast:: PathSegment ,
23232342 colons_before_params : bool ) {
23242343 if segment. ident . name != kw:: PathRoot {
2325- if segment. ident . name == kw:: DollarCrate {
2326- self . print_dollar_crate ( segment. ident ) ;
2327- } else {
2328- self . print_ident ( segment. ident ) ;
2329- }
2344+ self . print_ident ( segment. ident ) ;
23302345 if let Some ( ref args) = segment. args {
23312346 self . print_generic_args ( args, colons_before_params) ;
23322347 }
0 commit comments