Change:
Code: Generated docs: ! So what I want to do is create a macro inside . I don't want it to show up in crate root - I want it only in this module. Both of the re-exports above work just fine. However, in the generated docs, one of them has no docs and the other doesn't show up at all. I'm surprised that is "recursive" - shouldn't it only hide and not hide ? Is this a bug? Versions:
Is there any news on this? We would like to use something like that for diesel to.
This doesn't appear to be just an issue with macros either: Produces entirely empty rustdoc output!
I have a similar issue with modules: Essentially I want to present nested module structure (that is used to limit visibility within crate) as non-nested in docs by leveraging re-exports. I'm thinking of that would override of the definition if applied to : Without this when inlining is used it creates confusion since the same module is both visible at the root of the crate and nested within submodule. This also confuses IntelliJ Rust, it shows 2 suggestions for imports all the time and could use this to hide one of them.
This is causing quite a big issue for Rocket's docs. We'd really like to export macros only from specific modules, but this bug makes it impossible without also exporting them at the root. Specifically, this: Results in: index: foo: Which is expected. Now, by adding to 's declaration/definition... ...all_ instances of in the docs disappear, even though is still reachable and not hidden!
Here's a macro that (sort of) patches around this issue: Simply wrap a declaration with : One must be careful not to use features in expansion arms. As long as this issue exists, the macro will appear as in the right place without a docstring. Should this issue be fixed, nightly and stable docs will match.
It looks like this issue has been inactive for a while, but the problem is still there. I would like to know if there are more comments from members about said he had a discussion with and about this, but I didn't find it. that it looked fine to him.
I'm no longer a member of the rustdoc team, please don't ping me.
Technical information for everyone following this issue: I'm working on it (well, you can infer that from my PRs I suppose). One of the last blockers is actually : currently we merge both the 's and the item's attributes. Meaning that the is inherited. The problem is that it's currently not possible to filter the sub-attributes of an (for example, in , we want to keep ). So hopefully, once I figure out this part, I should be able to fix all the remaining issues at once.
So now only one issue remains:
FWIW, "back in the day" I did have a branch with an implementation tackling your situation, if you are interested:
I have a vague idea on how to fix it but I'm definitely interested into seeing how you did it. You sure you don't want to send a PR btw?

Discussion:
/// In case `i` is a non-hidden impl block, then we special-case it by changing the value /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility. <del> fn recurse_in_impl(&mut self, i: Item) -> Item { </del> <ins> fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item { </ins> let prev = mem::replace(&mut self.is_in_hidden_item, false); let ret = self.fold_item_recur(i); self.is_in_hidden_item = prev;

impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option<Item> { let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden); <del> let is_impl = matches!(*i.kind, clean::ImplItem(..)); </del> <ins> let is_impl_or_exported_macro = match *i.kind { clean::ImplItem(..) => true, // If the macro has the `#[macro_export]` attribute, it means it's accessible at the // crate level so it should be handled differently. clean::MacroItem(..) => { i.attrs.other_attrs.iter().any(|attr| attr.has_name(sym::macro_export)) } _ => false, }; </ins> let mut is_hidden = has_doc_hidden; <del> if !is_impl { </del> <ins> if !is_impl_or_exported_macro { </ins> is_hidden = self.is_in_hidden_item || has_doc_hidden; if !is_hidden && i.inline_stmt_id.is_none() { // We don't need to check if it's coming from a reexport since the reexport itself was

if self.update_retained { self.retained.insert(i.item_id); } <del> return Some(if is_impl { self.recurse_in_impl(i) </del> <ins> return Some(if is_impl_or_exported_macro { self.recurse_in_impl_or_exported_macro(i) </ins> } else { self.set_is_in_hidden_item_and_fold(false, i) });

<ins> // Regression test for <https://github.com/rust-lang/rust/issues/108231>. // Macros with `#[macro_export]` attribute should be visible at the top level // even if they are inside a doc hidden item. #![crate_name = "foo"] // @has 'foo/index.html' // @count - '//*[@id="main-content"]//a[@class="macro"]' 1 // @has - '//*[@id="main-content"]//a[@class="macro"]' 'foo' #[doc(hidden)] pub mod __internal { /// This one should be visible. #[macro_export] macro_rules! foo { () => {}; } /// This one should be hidden. macro_rules! bar { () => {}; } } </ins>

<ins> // Ensure that inlined reexport of hidden macros is working as expected. // Part of <https://github.com/rust-lang/rust/issues/59368>. #![crate_name = "foo"] // @has 'foo/index.html' // @has - '//*[@id="main-content"]//a[@href="macro.Macro2.html"]' 'Macro2' // @has 'foo/macro.Macro2.html' // @has - '//*[@class="docblock"]' 'Displayed' #[macro_export] #[doc(hidden)] macro_rules! foo { () => {}; } /// not displayed pub use crate::foo as Macro; /// Displayed #[doc(inline)] pub use crate::foo as Macro2; </ins>