@@ -585,38 +585,68 @@ 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+ let mut tokens = tokens. iter ( ) ;
593594 let mut out = String :: new ( ) ;
594- for matcher in matchers {
595+ while let Some ( mut token) = tokens. next ( ) {
596+ // If this an attr/derive rule, it looks like `attr() () => {}`, so the token needs to be
597+ // handled at the same time as the actual matcher.
598+ //
599+ // Without that, we would end up with `attr()` on one line and the matcher `()` on another.
600+ let pre = if matches ! ( token, TokenTree :: Token ( ..) ) {
601+ let pre = format ! ( "{}() " , render_macro_matcher( tcx, token) ) ;
602+ // Skipping the always empty `()` following the attr/derive ident.
603+ tokens. next ( ) ;
604+ let Some ( next) = tokens. next ( ) else {
605+ return out;
606+ } ;
607+ token = next;
608+ pre
609+ } else {
610+ String :: new ( )
611+ } ;
595612 writeln ! (
596613 out,
597- " {matcher} => {{ ... }}{arm_delim}" ,
598- matcher = render_macro_matcher( tcx, matcher ) ,
614+ " {pre}{ matcher} => {{ ... }}{arm_delim}" ,
615+ matcher = render_macro_matcher( tcx, token ) ,
599616 )
600617 . unwrap ( ) ;
618+ // We skip the `=>`, macro "body" and the delimiter closing that "body" since we don't
619+ // render them.
620+ tokens. next ( ) ;
621+ tokens. next ( ) ;
622+ tokens. next ( ) ;
601623 }
602624 out
603625}
604626
605627pub ( super ) fn display_macro_source ( tcx : TyCtxt < ' _ > , name : Symbol , def : & ast:: MacroDef ) -> String {
606628 // 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-
609629 if def. macro_rules {
610- format ! ( "macro_rules! {name} {{\n {arms}}}" , arms = render_macro_arms( tcx, matchers, ";" ) )
630+ format ! (
631+ "macro_rules! {name} {{\n {arms}}}" ,
632+ arms = render_macro_arms( tcx, & def. body. tokens, ";" )
633+ )
611634 } else {
612- if matchers . len ( ) <= 1 {
635+ if def . body . tokens . len ( ) <= 4 {
613636 format ! (
614637 "macro {name}{matchers} {{\n ...\n }}" ,
615- matchers =
616- matchers. map( |matcher| render_macro_matcher( tcx, matcher) ) . collect:: <String >( ) ,
638+ matchers = def
639+ . body
640+ . tokens
641+ . get( 0 )
642+ . map( |matcher| render_macro_matcher( tcx, matcher) )
643+ . unwrap_or_default( ) ,
617644 )
618645 } else {
619- format ! ( "macro {name} {{\n {arms}}}" , arms = render_macro_arms( tcx, matchers, "," ) )
646+ format ! (
647+ "macro {name} {{\n {arms}}}" ,
648+ arms = render_macro_arms( tcx, & def. body. tokens, "," )
649+ )
620650 }
621651 }
622652}
0 commit comments