@@ -17,6 +17,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
1717use  rustc_middle:: mir:: interpret:: ConstValue ; 
1818use  rustc_middle:: ty:: subst:: { GenericArgKind ,  SubstsRef } ; 
1919use  rustc_middle:: ty:: { self ,  DefIdTree ,  TyCtxt } ; 
20+ use  rustc_session:: parse:: ParseSess ; 
21+ use  rustc_span:: source_map:: FilePathMapping ; 
2022use  rustc_span:: symbol:: { kw,  sym,  Symbol } ; 
2123use  std:: fmt:: Write  as  _; 
2224use  std:: mem; 
@@ -486,20 +488,67 @@ crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
486488/// Render a sequence of macro arms in a format suitable for displaying to the user 
487489/// as part of an item declaration. 
488490pub ( super )  fn  render_macro_arms < ' a > ( 
491+     tcx :  TyCtxt < ' _ > , 
489492    matchers :  impl  Iterator < Item  = & ' a  TokenTree > , 
490493    arm_delim :  & str , 
491494)  -> String  { 
492495    let  mut  out = String :: new ( ) ; 
493496    for  matcher in  matchers { 
494-         writeln ! ( out,  "    {} => {{ ... }}{}" ,  render_macro_matcher( matcher) ,  arm_delim) . unwrap ( ) ; 
497+         writeln ! ( out,  "    {} => {{ ... }}{}" ,  render_macro_matcher( tcx,  matcher) ,  arm_delim) 
498+             . unwrap ( ) ; 
495499    } 
496500    out
497501} 
498502
499503/// Render a macro matcher in a format suitable for displaying to the user 
500504/// as part of an item declaration. 
501- pub ( super )  fn  render_macro_matcher ( matcher :  & TokenTree )  -> String  { 
502-     rustc_ast_pretty:: pprust:: tt_to_string ( matcher) 
505+ pub ( super )  fn  render_macro_matcher ( tcx :  TyCtxt < ' _ > ,  matcher :  & TokenTree )  -> String  { 
506+     if  let  Some ( snippet)  = snippet_equal_to_token ( tcx,  matcher)  { 
507+         snippet
508+     }  else  { 
509+         rustc_ast_pretty:: pprust:: tt_to_string ( matcher) 
510+     } 
511+ } 
512+ 
513+ /// Find the source snippet for this token's Span, reparse it, and return the 
514+ /// snippet if the reparsed TokenTree matches the argument TokenTree. 
515+ fn  snippet_equal_to_token ( tcx :  TyCtxt < ' _ > ,  matcher :  & TokenTree )  -> Option < String >  { 
516+     // Find what rustc thinks is the source snippet. 
517+     // This may not actually be anything meaningful if this matcher was itself 
518+     // generated by a macro. 
519+     let  source_map = tcx. sess . source_map ( ) ; 
520+     let  span = matcher. span ( ) ; 
521+     let  snippet = source_map. span_to_snippet ( span) . ok ( ) ?; 
522+ 
523+     // Create a Parser. 
524+     let  sess = ParseSess :: new ( FilePathMapping :: empty ( ) ) ; 
525+     let  file_name = source_map. span_to_filename ( span) ; 
526+     let  mut  parser =
527+         match  rustc_parse:: maybe_new_parser_from_source_str ( & sess,  file_name,  snippet. clone ( ) )  { 
528+             Ok ( parser)  => parser, 
529+             Err ( diagnostics)  => { 
530+                 for  mut  diagnostic in  diagnostics { 
531+                     diagnostic. cancel ( ) ; 
532+                 } 
533+                 return  None ; 
534+             } 
535+         } ; 
536+ 
537+     // Reparse a single token tree. 
538+     let  mut  reparsed_trees = match  parser. parse_all_token_trees ( )  { 
539+         Ok ( reparsed_trees)  => reparsed_trees, 
540+         Err ( mut  diagnostic)  => { 
541+             diagnostic. cancel ( ) ; 
542+             return  None ; 
543+         } 
544+     } ; 
545+     if  reparsed_trees. len ( )  != 1  { 
546+         return  None ; 
547+     } 
548+     let  reparsed_tree = reparsed_trees. pop ( ) . unwrap ( ) ; 
549+ 
550+     // Compare against the original tree. 
551+     if  reparsed_tree. eq_unspanned ( matcher)  {  Some ( snippet)  }  else  {  None  } 
503552} 
504553
505554pub ( super )  fn  display_macro_source ( 
@@ -514,21 +563,21 @@ pub(super) fn display_macro_source(
514563    let  matchers = tts. chunks ( 4 ) . map ( |arm| & arm[ 0 ] ) ; 
515564
516565    if  def. macro_rules  { 
517-         format ! ( "macro_rules! {} {{\n {}}}" ,  name,  render_macro_arms( matchers,  ";" ) ) 
566+         format ! ( "macro_rules! {} {{\n {}}}" ,  name,  render_macro_arms( cx . tcx ,   matchers,  ";" ) ) 
518567    }  else  { 
519568        if  matchers. len ( )  <= 1  { 
520569            format ! ( 
521570                "{}macro {}{} {{\n     ...\n }}" , 
522571                vis. to_src_with_space( cx. tcx,  def_id) , 
523572                name, 
524-                 matchers. map( render_macro_matcher) . collect:: <String >( ) , 
573+                 matchers. map( |matcher|  render_macro_matcher( cx . tcx ,  matcher ) ) . collect:: <String >( ) , 
525574            ) 
526575        }  else  { 
527576            format ! ( 
528577                "{}macro {} {{\n {}}}" , 
529578                vis. to_src_with_space( cx. tcx,  def_id) , 
530579                name, 
531-                 render_macro_arms( matchers,  "," ) , 
580+                 render_macro_arms( cx . tcx ,   matchers,  "," ) , 
532581            ) 
533582        } 
534583    } 
0 commit comments