Skip to content

Fix handling of reexported macro in doc hidden items #108241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/librustdoc/passes/strip_hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> {

/// 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.
fn recurse_in_impl(&mut self, i: Item) -> Item {
fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
let prev = mem::replace(&mut self.is_in_hidden_item, false);
let ret = self.fold_item_recur(i);
self.is_in_hidden_item = prev;
Expand All @@ -73,9 +73,17 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> {
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);
let is_impl = matches!(*i.kind, clean::ImplItem(..));
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,
};
let mut is_hidden = has_doc_hidden;
if !is_impl {
if !is_impl_or_exported_macro {
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
Expand All @@ -92,8 +100,8 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
if self.update_retained {
self.retained.insert(i.item_id);
}
return Some(if is_impl {
self.recurse_in_impl(i)
return Some(if is_impl_or_exported_macro {
self.recurse_in_impl_or_exported_macro(i)
} else {
self.set_is_in_hidden_item_and_fold(false, i)
});
Expand Down
23 changes: 23 additions & 0 deletions tests/rustdoc/issue-108231.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 {
() => {};
}
}
22 changes: 22 additions & 0 deletions tests/rustdoc/reexport-hidden-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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;