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