Skip to content

rustdoc: Inherit inline attributes for declarative macros#154902

Open
shivendra02467 wants to merge 1 commit intorust-lang:mainfrom
shivendra02467:fix-rustdoc-macro-inline
Open

rustdoc: Inherit inline attributes for declarative macros#154902
shivendra02467 wants to merge 1 commit intorust-lang:mainfrom
shivendra02467:fix-rustdoc-macro-inline

Conversation

@shivendra02467
Copy link
Copy Markdown

@shivendra02467 shivendra02467 commented Apr 6, 2026

When explicitly re-exporting a declarative macro by name, rustdoc previously bypassed intermediate re-exports and dropped #[doc(inline)] attributes, causing the macro to be incorrectly stripped if the original definition was #[doc(hidden)].

This updates generate_item_with_correct_attrs to walk the reexport_chain specifically for declarative macros, allowing them to inherit inline attributes exactly as glob imports do, while preserving strict visibility rules for standard items.

Fixes #154694

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Apr 6, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 6, 2026

r? @lolbinarycat

rustbot has assigned @lolbinarycat.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: rustdoc
  • rustdoc expanded to 9 candidates
  • Random selection from GuillaumeGomez, camelid, fmease, lolbinarycat, notriddle

@rustbot

This comment has been minimized.

When explicitly re-exporting a declarative macro by name, rustdoc
previously bypassed intermediate re-exports and dropped `#[doc(inline)]`
attributes, causing the macro to be incorrectly stripped if the original
definition was `#[doc(hidden)]`.

This updates `generate_item_with_correct_attrs` to walk the
`reexport_chain` specifically for declarative macros, allowing them to
inherit inline attributes exactly as glob imports do, while preserving
strict visibility rules for standard items.
@shivendra02467 shivendra02467 force-pushed the fix-rustdoc-macro-inline branch from 9ada003 to e571df1 Compare April 6, 2026 17:20
@lolbinarycat
Copy link
Copy Markdown
Contributor

lolbinarycat commented Apr 6, 2026

thanks for the contribution!

I haven't looked at the code in-depth yet, but this will need a regression test, I would recommend the rustdoc-html test suite. If you have any issues creating a test, please let me know, both so I can help and so the documentation can be improved for future contributors.

EDIT: nvm there is a regression test, not sure how i missed that.

@shivendra02467
Copy link
Copy Markdown
Author

thanks for the contribution!

I haven't looked at the code in-depth yet, but this will need a regression test, I would recommend the rustdoc-html test suite. If you have any issues creating a test, please let me know, both so I can help and so the documentation can be improved for future contributors.

EDIT: nvm there is a regression test, not sure how i missed that.

No worries at all! Thanks for taking a look. Take your time with the review, and just let me know if you need any adjustments to the test or the logic once you get a chance to dig into it.

@lolbinarycat
Copy link
Copy Markdown
Contributor

The logic is a bit naive, reexport_chain has no knowledge of doc(hidden), so we need to handle that properly.

Specifically, as we walk backwards through the import chain1, if we hit a doc(hidden) attribute before or at the same time as we find a doc(inline) attribute, we need to stop searching and say the macro is hidden.

The code already had a decent bit of duplication going on, and the extra logic would only add to that, so please factor out the check (or at least a decent portion of it) into a utility function or method, perhaps named something like should_macro_reexport_be_hidden.

Modified test with extra details in comments
// Regression test for <https://github.com/rust-lang/rust/issues/154694>.
// The goal is to ensure that declarative macros re-exported by name
// inherit the `#[doc(inline)]` attribute from intermediate re-exports,
// matching the behavior of glob re-exports.

#![crate_name = "foo"]

#[macro_use]
mod macros {
    #[macro_export]
    #[doc(hidden)]
    macro_rules! explicit_macro {
        () => {};
    }

    #[macro_export]
    #[doc(hidden)]
    macro_rules! wild_macro {
        () => {};
    }

    #[macro_export]
    #[doc(hidden)]
    macro_rules! actually_hidden_macro {
        () => {};
    }

    #[macro_export]
    #[doc(hidden)]
    macro_rules! actually_hidden_wild_macro {
        () => {};
    }


    #[macro_export]
    #[doc(hidden)]
    macro_rules! actually_hidden_indirect_macro {
        () => {};
    }

}

// We would like to have parity between macro inlining and inlining other items,
// so I'm providing a struct for reference.
#[doc(hidden)]
pub struct HiddenStruct;

#[doc(hidden)]
pub struct IndirectlyHiddenStruct;


pub mod bar {
    mod hidden_explicit {
        #[doc(inline)]
        pub use crate::explicit_macro;
    }

    mod hidden_wild {
        #[doc(inline)]
        pub use crate::wild_macro;
    }

    mod actually_hidden {
        // BUG: as demonstrated by the `actually_hidden_struct` module, when both
        // `doc(hidden)` and `doc(inline)` are specified, `doc(hidden)`
        // should take priority.
        #[doc(hidden)]
        #[doc(inline)]
        pub use crate::actually_hidden_macro;
    }

    mod actually_hidden_indirect_inner {
        #[doc(inline)]
        pub use crate::actually_hidden_indirect_macro;
    }

    mod actually_hidden_indirect {
        // BUG: when there is a chain of imports, we should stop looking as soon as soon as we hit
        // something with `doc(hidden)`.
        // IMO this is the more important of the two bugs.
        #[doc(hidden)]
        pub use super::actually_hidden_indirect_inner::actually_hidden_indirect_macro;
    }

    mod actually_hidden_indirect_struct_inner {
        #[doc(inline)]
        pub use crate::IndirectlyHiddenStruct;
    }

    mod actually_hidden_indirect_struct {
        #[doc(hidden)]
        pub use super::actually_hidden_indirect_struct_inner::IndirectlyHiddenStruct;
    }

    mod actually_hidden_wild {
        #[doc(hidden)]
        #[doc(inline)]
        pub use crate::actually_hidden_wild_macro;
    }

    mod actually_hidden_struct {
        #[doc(inline)]
        #[doc(hidden)]
        pub use crate::HiddenStruct;
    }


    // First, we check that the explicitly named macro inherits the inline attribute
    // from `hidden_explicit` and is successfully rendered.
    //@ has 'foo/bar/macro.explicit_macro.html'
    //@ has 'foo/bar/index.html' '//a[@href="macro.explicit_macro.html"]' 'explicit_macro'
    pub use self::hidden_explicit::explicit_macro;

    // Next, we ensure that the glob-imported macro continues to render correctly
    // as a control case.
    //@ has 'foo/bar/macro.wild_macro.html'
    //@ has 'foo/bar/index.html' '//a[@href="macro.wild_macro.html"]' 'wild_macro'
    pub use self::hidden_wild::*;

    //@ !has 'foo/bar/macro.actually_hidden_macro.html'
    pub use self::actually_hidden::actually_hidden_macro;
    //@ !has 'foo/bar/macro.actually_hidden_wild_macro.html'
    pub use self::actually_hidden_wild::*;
    //@ !has 'foo/bar/struct.HiddenStruct.html'
    pub use self::actually_hidden_struct::HiddenStruct;
    //@ !has 'foo/bar/macro.actually_hidden_indirect_macro.html'
    pub use self::actually_hidden_indirect::actually_hidden_indirect_macro;
    //@ !has 'foo/bar/struct.IndirectlyHiddenStruct.html'
    pub use self::actually_hidden_indirect_struct::IndirectlyHiddenStruct;
}

Footnotes

  1. I don't know if reexport_chain walks forwards or backwards by default, will require some experimentation.

@lolbinarycat
Copy link
Copy Markdown
Contributor

@rustbot author

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 6, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 6, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Re-export a declarative macro isn't rendered by rustdoc if named explicitly

3 participants