@@ -585,38 +585,69 @@ pub(crate) static RUSTDOC_VERSION: Lazy<&'static str> =
585585
586586/// Render a sequence of macro arms in a format suitable for displaying to the user
587587/// as part of an item declaration.
588- fn render_macro_arms < ' a > (
588+ fn render_macro_arms (
589589 tcx : TyCtxt < ' _ > ,
590- matchers : impl Iterator < Item = & ' a TokenTree > ,
590+ tokens : & rustc_ast :: tokenstream :: TokenStream ,
591591 arm_delim : & str ,
592592) -> String {
593+ eprintln ! ( "============>\n {tokens:#?}" ) ;
594+ let mut tokens = tokens. iter ( ) ;
593595 let mut out = String :: new ( ) ;
594- for matcher in matchers {
596+ while let Some ( mut token) = tokens. next ( ) {
597+ // If this an attr/derive rule, it looks like `attr() () => {}`, so the token needs to be
598+ // handled at the same time as the actual matcher.
599+ //
600+ // Without that, we would end up with `attr()` on one line and the matcher `()` on another.
601+ let pre = if matches ! ( token, TokenTree :: Token ( ..) ) {
602+ let pre = format ! ( "{}() " , render_macro_matcher( tcx, token) ) ;
603+ // Skipping the always empty `()` following the attr/derive ident.
604+ tokens. next ( ) ;
605+ let Some ( next) = tokens. next ( ) else {
606+ return out;
607+ } ;
608+ token = next;
609+ pre
610+ } else {
611+ String :: new ( )
612+ } ;
595613 writeln ! (
596614 out,
597- " {matcher} => {{ ... }}{arm_delim}" ,
598- matcher = render_macro_matcher( tcx, matcher ) ,
615+ " {pre}{ matcher} => {{ ... }}{arm_delim}" ,
616+ matcher = render_macro_matcher( tcx, token ) ,
599617 )
600618 . unwrap ( ) ;
619+ // We skip the `=>`, macro "body" and the delimiter closing that "body" since we don't
620+ // render them.
621+ tokens. next ( ) ;
622+ tokens. next ( ) ;
623+ tokens. next ( ) ;
601624 }
602625 out
603626}
604627
605628pub ( super ) fn display_macro_source ( tcx : TyCtxt < ' _ > , name : Symbol , def : & ast:: MacroDef ) -> String {
606629 // Extract the spans of all matchers. They represent the "interface" of the macro.
607- let matchers = def. body . tokens . chunks ( 4 ) . map ( |arm| & arm[ 0 ] ) ;
608-
609630 if def. macro_rules {
610- format ! ( "macro_rules! {name} {{\n {arms}}}" , arms = render_macro_arms( tcx, matchers, ";" ) )
631+ format ! (
632+ "macro_rules! {name} {{\n {arms}}}" ,
633+ arms = render_macro_arms( tcx, & def. body. tokens, ";" )
634+ )
611635 } else {
612- if matchers . len ( ) <= 1 {
636+ if def . body . tokens . len ( ) <= 4 {
613637 format ! (
614638 "macro {name}{matchers} {{\n ...\n }}" ,
615- matchers =
616- matchers. map( |matcher| render_macro_matcher( tcx, matcher) ) . collect:: <String >( ) ,
639+ matchers = def
640+ . body
641+ . tokens
642+ . get( 0 )
643+ . map( |matcher| render_macro_matcher( tcx, matcher) )
644+ . unwrap_or_default( ) ,
617645 )
618646 } else {
619- format ! ( "macro {name} {{\n {arms}}}" , arms = render_macro_arms( tcx, matchers, "," ) )
647+ format ! (
648+ "macro {name} {{\n {arms}}}" ,
649+ arms = render_macro_arms( tcx, & def. body. tokens, "," )
650+ )
620651 }
621652 }
622653}
0 commit comments