about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/passes/strip_hidden.rs18
-rw-r--r--tests/rustdoc/issue-108231.rs23
-rw-r--r--tests/rustdoc/reexport-hidden-macro.rs22
3 files changed, 58 insertions, 5 deletions
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 8c733ddefc0..890b3e8d67f 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -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;
@@ -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
@@ -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)
             });
diff --git a/tests/rustdoc/issue-108231.rs b/tests/rustdoc/issue-108231.rs
new file mode 100644
index 00000000000..684f0494fd5
--- /dev/null
+++ b/tests/rustdoc/issue-108231.rs
@@ -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 {
+        () => {};
+    }
+}
diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport-hidden-macro.rs
new file mode 100644
index 00000000000..afcfa979616
--- /dev/null
+++ b/tests/rustdoc/reexport-hidden-macro.rs
@@ -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;