Repository: rust-lang/rust
Pull request #137534: [rustdoc] hide item that is not marked as doc(inline) and whose src is doc(hidden)
Author: login: xizheyin
Labels: name: T-rustdoc
description: Relevant to the rustdoc team, which will review and decide on the PR/issue.
name: S-waiting-on-bors
description: Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
name: perf-regression
description: Performance regression.
name: T-rustdoc-frontend
description: Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.
Created: 2025-02-24T11:27:30Z | Merged: 2025-03-07T02:55:42Z

Part of #137342 

![image](https://github.com/user-attachments/assets/68b4649a-a64a-43b2-8a73-6ac92b486e9e)





Diff:
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index a71bb62e56c74..bcdca862862d4 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -7,9 +7,8 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 use tracing::debug;
 
-use crate::clean;
 use crate::clean::utils::inherits_doc_hidden;
-use crate::clean::{Item, ItemIdSet};
+use crate::clean::{self, Item, ItemIdSet, reexport_chain};
 use crate::core::DocContext;
 use crate::fold::{DocFolder, strip_item};
 use crate::passes::{ImplStripper, Pass};
@@ -89,6 +88,25 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
+            && let Some(source_did) = source.did
+            && let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local())
+        {
+            let reexports = reexport_chain(self.tcx, import_def_id, source_did);
+
+            // Check if any reexport in the chain has a hidden source
+            let has_hidden_source = reexports
+                .iter()
+                .filter_map(|reexport| reexport.id())
+                .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did))
+                || self.tcx.is_doc_hidden(source_did);
+
+            if has_hidden_source {
+                return None;
+            }
+        }
+
         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
diff --git a/tests/rustdoc/doc-hidden-reexports-109449.rs b/tests/rustdoc/doc-hidden-reexports-109449.rs
index 8f195544120af..78b9214300a95 100644
--- a/tests/rustdoc/doc-hidden-reexports-109449.rs
+++ b/tests/rustdoc/doc-hidden-reexports-109449.rs
@@ -26,21 +26,21 @@ pub mod single_reexport {
     //@ has 'foo/single_reexport/index.html'
 
     // First we check that we have 4 type aliases.
-    //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 4
+    //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 0
 
     // Then we check that we have the correct link for each re-export.
 
     //@ !has - '//*[@href="struct.Foo.html"]' 'Foo'
-    //@ has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
+    //@ !has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
     pub use crate::private_module::Public as Foo;
     //@ !has - '//*[@href="type.Foo2.html"]' 'Foo2'
-    //@ has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;'
+    //@ !has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;'
     pub use crate::private_module::Bar as Foo2;
     //@ !has - '//*[@href="type.Yo.html"]' 'Yo'
-    //@ has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
+    //@ !has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
     pub use crate::Bar3 as Yo;
     //@ !has - '//*[@href="struct.Yo2.html"]' 'Yo2'
-    //@ has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
+    //@ !has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
     pub use crate::FooFoo as Yo2;
 
     // Checking that each file is also created as expected.
@@ -70,19 +70,19 @@ pub mod single_reexport_no_inline {
     //@ has - '//*[@id="main-content"]/*[@class="section-header"]' 'Re-exports'
 
     // Now we check that we don't have links to the items, just `pub use`.
-    //@ has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;'
+    //@ !has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;'
     //@ !has - '//*[@id="main-content"]//a' 'XFoo'
     #[doc(no_inline)]
     pub use crate::private_module::Public as XFoo;
-    //@ has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;'
+    //@ !has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;'
     //@ !has - '//*[@id="main-content"]//a' 'Foo2'
     #[doc(no_inline)]
     pub use crate::private_module::Bar as Foo2;
-    //@ has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;'
+    //@ !has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;'
     //@ !has - '//*[@id="main-content"]//a' 'Yo'
     #[doc(no_inline)]
     pub use crate::Bar3 as Yo;
-    //@ has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;'
+    //@ !has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;'
     //@ !has - '//*[@id="main-content"]//a' 'Yo2'
     #[doc(no_inline)]
     pub use crate::FooFoo as Yo2;
diff --git a/tests/rustdoc/doc-hidden-source.rs b/tests/rustdoc/doc-hidden-source.rs
new file mode 100644
index 0000000000000..b6bc622dd584f
--- /dev/null
+++ b/tests/rustdoc/doc-hidden-source.rs
@@ -0,0 +1,16 @@
+// Test for <https://github.com/rust-lang/rust/issues/137342>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ !has - '//*[@id="main-content"]//*[@class="struct"]' 'Bar'
+#[doc(hidden)]
+pub struct Bar;
+
+//@ !has - '//*' 'pub use crate::Bar as A;'
+pub use crate::Bar as A;
+//@ !has - '//*' 'pub use crate::A as B;'
+pub use crate::A as B;
+//@ has - '//dt/a[@class="struct"]' 'C'
+#[doc(inline)]
+pub use crate::Bar as C;
diff --git a/tests/rustdoc/inline_cross/inline_hidden.rs b/tests/rustdoc/inline_cross/inline_hidden.rs
index 49ca2db6a2245..f6727de2cc67f 100644
--- a/tests/rustdoc/inline_cross/inline_hidden.rs
+++ b/tests/rustdoc/inline_cross/inline_hidden.rs
@@ -6,7 +6,7 @@ extern crate rustdoc_hidden;
 
 //@ has inline_hidden/index.html
 // Ensures this item is not inlined.
-//@ has - '//*[@id="reexport.Foo"]/code' 'pub use rustdoc_hidden::Foo;'
+//@ !has - '//*[@id="reexport.Foo"]/code' 'pub use rustdoc_hidden::Foo;'
 #[doc(no_inline)]
 pub use rustdoc_hidden::Foo;
 
@@ -16,7 +16,7 @@ pub use rustdoc_hidden::Foo;
 pub use rustdoc_hidden::Foo as Inlined;
 
 // Even with this import, we should not see `Foo`.
-//@ count - '//dt' 4
+//@ count - '//dt' 3
 //@ has - '//dt/a[@class="struct"]' 'Bar'
 //@ has - '//dt/a[@class="fn"]' 'foo'
 pub use rustdoc_hidden::*;
diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs
index e4a406c3845ad..aef302eb0b29a 100644
--- a/tests/rustdoc/reexport-attr-merge.rs
+++ b/tests/rustdoc/reexport-attr-merge.rs
@@ -18,7 +18,7 @@ pub use Foo1 as Foo2;
 
 // First we ensure that only the reexport `Bar2` and the inlined struct `Bar`
 // are inlined.
-//@ count - '//a[@class="struct"]' 2
+//@ count - '//a[@class="struct"]' 1
 // Then we check that `cfg` is displayed for base item, but not for intermediate re-exports.
 //@ has - '//*[@class="stab portability"]' 'foo'
 //@ !has - '//*[@class="stab portability"]' 'bar'
@@ -29,5 +29,5 @@ pub use Foo2 as Bar;
 
 // This one should appear but `Bar2` won't be linked because there is no
 // `#[doc(inline)]`.
-//@ has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
+//@ !has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
 pub use Foo2 as Bar2;
diff --git a/tests/rustdoc/reexport-doc-hidden-inside-private.rs b/tests/rustdoc/reexport-doc-hidden-inside-private.rs
index 8e194ef74fb82..bae2aa78ec7a3 100644
--- a/tests/rustdoc/reexport-doc-hidden-inside-private.rs
+++ b/tests/rustdoc/reexport-doc-hidden-inside-private.rs
@@ -9,8 +9,8 @@ mod private_module {
 }
 
 //@ has 'foo/index.html'
-//@ has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
+//@ !has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
 pub use crate::private_module::Public as Foo;
 // Glob re-exports with no visible items should not be displayed.
-//@ count - '//*[@class="item-table reexports"]/dt' 1
+//@ count - '//*[@class="item-table reexports"]/dt' 0
 pub use crate::private_module::*;
diff --git a/tests/rustdoc/reexport-doc-hidden.rs b/tests/rustdoc/reexport-doc-hidden.rs
index b912362f2987a..1468e9ad957f7 100644
--- a/tests/rustdoc/reexport-doc-hidden.rs
+++ b/tests/rustdoc/reexport-doc-hidden.rs
@@ -8,7 +8,7 @@
 pub type Type = u32;
 
 //@ has 'foo/index.html'
-//@ has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;'
+//@ !has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;'
 pub use crate::Type as Type2;
 
 //@ count - '//*[@id="reexport.Type3"]' 0
@@ -21,5 +21,5 @@ macro_rules! foo {
     () => {};
 }
 
-//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
 pub use crate::foo as Macro;
diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport-hidden-macro.rs
index 9b83bca3906d2..7345149c64522 100644
--- a/tests/rustdoc/reexport-hidden-macro.rs
+++ b/tests/rustdoc/reexport-hidden-macro.rs
@@ -5,7 +5,7 @@
 
 //@ has 'foo/index.html'
 //@ has - '//*[@id="main-content"]//a[@href="macro.Macro2.html"]' 'Macro2'
-//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
 
 //@ has 'foo/macro.Macro2.html'
 //@ has - '//*[@class="docblock"]' 'Displayed'
diff --git a/tests/rustdoc/reexport-of-doc-hidden.rs b/tests/rustdoc/reexport-of-doc-hidden.rs
index 21511bc2aea99..e901d0ff8a2bc 100644
--- a/tests/rustdoc/reexport-of-doc-hidden.rs
+++ b/tests/rustdoc/reexport-of-doc-hidden.rs
@@ -12,13 +12,13 @@ macro_rules! foo {
 }
 
 //@ has 'foo/index.html'
-//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
 pub use crate::foo as Macro;
-//@ has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
+//@ !has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
 pub use crate::foo as Macro2;
-//@ has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
+//@ !has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
 pub use crate::Bar as Boo;
-//@ has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;'
+//@ !has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;'
 pub use crate::Bar as Boo2;
 
 pub fn fofo() {}
@@ -30,9 +30,9 @@ pub use crate::fofo as f2;
 
 pub mod sub {
     //@ has 'foo/sub/index.html'
-    //@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
+    //@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
     pub use crate::foo as Macro;
-    //@ has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
+    //@ !has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
     pub use crate::foo as Macro2;
 
     //@ has - '//*[@id="reexport.f1"]/code' 'pub use crate::fofo as f1;'


Reviews:
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:36:44Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:36:54Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:38:43Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:38:54Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:39:02Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T13:40:28Z
user: login: GuillaumeGomez
body: Heading to the right direction, but still changes to be done.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-03T15:14:17Z
user: login: xizheyin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:02:10Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:09:47Z
user: login: xizheyin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:45:20Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:48:22Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:51:14Z
user: login: xizheyin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:51:36Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T16:53:14Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T17:42:27Z
user: login: xizheyin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T18:04:23Z
user: login: GuillaumeGomez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-03T22:04:03Z
user: login: GuillaumeGomez
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-03T22:04:35Z

Review comments:
diff_hunk: @@ -12,14 +12,14 @@ macro_rules! foo {
 }
 
 //@ has 'foo/index.html'
-//@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
-pub use crate::foo as Macro;
-//@ has - '//*[@id="reexport.Macro2"]/code' 'pub use crate::foo as Macro2;'
-pub use crate::foo as Macro2;
-//@ has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
+//@ !has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
path: tests/rustdoc/reexport-of-doc-hidden.rs
user: login: GuillaumeGomez
body: Please move this check just above the line it's checking.
created_at: 2025-02-27T13:36:44Z
author_association: MEMBER
diff_hunk: @@ -31,12 +31,11 @@ pub use crate::fofo as f2;
 pub mod sub {
     //@ has 'foo/sub/index.html'
     //@ has - '//*[@id="reexport.Macro"]/code' 'pub use crate::foo as Macro;'
path: tests/rustdoc/reexport-of-doc-hidden.rs
user: login: GuillaumeGomez
body: Same here.
created_at: 2025-02-27T13:36:54Z
author_association: MEMBER
diff_hunk: @@ -12,22 +12,19 @@ pub struct Foo;
 
 #[doc(hidden, no_inline, cfg(feature = "bar"))]
 pub use Foo as Foo1;
-
path: tests/rustdoc/reexport-attr-merge.rs
user: login: GuillaumeGomez
body: Please keep the empty lines here and below (easier to read and also smaller diff).
created_at: 2025-02-27T13:38:43Z
author_association: MEMBER
diff_hunk: @@ -89,6 +130,25 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+        debug!(
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: Please remove.
created_at: 2025-02-27T13:38:54Z
author_association: MEMBER
diff_hunk: @@ -89,6 +130,25 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+        debug!(
+            "kkkkkkkkkkkkkk {:?}, item: {:?}, has_doc_hidden: {}, is_in_hidden_item: {}\n",
+            i.name, i, has_doc_hidden, self.is_in_hidden_item
+        );
+
+        // if self.hidden_items.iter().any(|item| item.item_id == i.item_id) {
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: Please remove.
created_at: 2025-02-27T13:39:02Z
author_association: MEMBER
diff_hunk: @@ -25,6 +25,28 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
     let mut retained = ItemIdSet::default();
     let is_json_output = cx.is_json_output();
 
+    let all_items = collect_items(&krate);
+
+    // Collect hidden items
+    let hidden_items: Vec<_> =
+        all_items.iter().filter(|item| item.is_doc_hidden()).cloned().collect();
+
+    // Map import items to their hidden source items
+    let source_items: FxHashMap<_, _> = all_items
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: Normally you can use [reexport_chain](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/metadata/struct.ModChild.html#structfield.reexport_chain) to get this info.
created_at: 2025-02-27T13:40:27Z
author_association: MEMBER
diff_hunk: @@ -89,6 +108,34 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
+                let reexports = reexport_chain(self.tcx, import_def_id, source_did);
+
+                // Check if any reexport in the chain has a hidden source
+                let has_hidden_source =
+                    reexports.iter().filter_map(|reexport| reexport.id()).any(|reexport_did| {
+                        self.all_items
+                            .iter()
+                            .find(|item| item.def_id() == Some(reexport_did))
+                            .and_then(|item| {
+                                if let clean::ItemKind::ImportItem(import) = &item.kind {
+                                    import.source.did.map(|did| self.tcx.is_doc_hidden(did))
+                                } else {
+                                    None
+                                }
+                            })
+                            .unwrap_or(false)
+                    });
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: So if I understand correctly: `self.all_items` is actually only the crate-level items (and not all items), then you iterate on these top-level items to find `use` items and check if they are `doc(hidden)`. Is there a reason you want to only check `ImportItem`? What happens if you check all items (including the original one)?

And also, you used `is_doc_hidden`, so you already are aware of it, so why keeping `all_items`?

If my hypothesis is correct, your code could become:

```suggestion
                let has_hidden_source = reexports.iter()
                    .filter_map(|reexport| reexport.id())
                    .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did));
```
created_at: 2025-03-03T15:14:03Z
author_association: MEMBER
diff_hunk: @@ -89,6 +108,34 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
+                let reexports = reexport_chain(self.tcx, import_def_id, source_did);
+
+                // Check if any reexport in the chain has a hidden source
+                let has_hidden_source =
+                    reexports.iter().filter_map(|reexport| reexport.id()).any(|reexport_did| {
+                        self.all_items
+                            .iter()
+                            .find(|item| item.def_id() == Some(reexport_did))
+                            .and_then(|item| {
+                                if let clean::ItemKind::ImportItem(import) = &item.kind {
+                                    import.source.did.map(|did| self.tcx.is_doc_hidden(did))
+                                } else {
+                                    None
+                                }
+                            })
+                            .unwrap_or(false)
+                    });
path: src/librustdoc/passes/strip_hidden.rs
user: login: xizheyin
body: `collect_all_items` recursively collects the items in the module, I did this because I found that reexport would only parse the `use` statements and the sources would not be obtained. For example, 
```
#[doc(hidden)]
pub fn hidden_self() {}

#[doc(hidden)]
pub mod hidden_m {
    pub fn hidden_super() {}
}

pub use crate::hidden_m::hidden_super as hidden_super_reexport;
pub use crate::hidden_self as hidden_self_reexport;

#[doc(inline)]
pub use crate::hidden_m::hidden_super as hidden_super_reexport_inline;
#[doc(inline)]
pub use crate::hidden_self as hidden_self_reexport_inline;
```
In this code,  `reexport_chain()` give me just the defid of `pub use crate::hidden_self as hidden_self_reexport;
`,  which is `reexports: [Single(DefId(0:7 ~ rustdoc_hidden_test[8c93]::{use#2}))]`.
But I should get the source of it, which is `#[doc(hidden)]pub fn hidden_self() {}`.
So, I do it to track the source of a reexport.
created_at: 2025-03-03T16:02:09Z
author_association: MEMBER
diff_hunk: @@ -89,6 +108,34 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
+                let reexports = reexport_chain(self.tcx, import_def_id, source_did);
+
+                // Check if any reexport in the chain has a hidden source
+                let has_hidden_source =
+                    reexports.iter().filter_map(|reexport| reexport.id()).any(|reexport_did| {
+                        self.all_items
+                            .iter()
+                            .find(|item| item.def_id() == Some(reexport_did))
+                            .and_then(|item| {
+                                if let clean::ItemKind::ImportItem(import) = &item.kind {
+                                    import.source.did.map(|did| self.tcx.is_doc_hidden(did))
+                                } else {
+                                    None
+                                }
+                            })
+                            .unwrap_or(false)
+                    });
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: Unless I missed something, `collect_all_items` is not recursive. You already have the `source` in `if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {`, it's the same source for all reexports.
created_at: 2025-03-03T16:09:47Z
author_association: MEMBER
diff_hunk: @@ -89,6 +108,34 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
+                let reexports = reexport_chain(self.tcx, import_def_id, source_did);
+
+                // Check if any reexport in the chain has a hidden source
+                let has_hidden_source =
+                    reexports.iter().filter_map(|reexport| reexport.id()).any(|reexport_did| {
+                        self.all_items
+                            .iter()
+                            .find(|item| item.def_id() == Some(reexport_did))
+                            .and_then(|item| {
+                                if let clean::ItemKind::ImportItem(import) = &item.kind {
+                                    import.source.did.map(|did| self.tcx.is_doc_hidden(did))
+                                } else {
+                                    None
+                                }
+                            })
+                            .unwrap_or(false)
+                    });
path: src/librustdoc/passes/strip_hidden.rs
user: login: xizheyin
body: Sorry, I forgot to recurse and didn't notice that `import.source` is the most starting point of the export. I changed the logic as you suggested, checking the reexport chain and also checking the source.  Now its a clean logic, thanks.

```
                let has_hidden_source = reexports
                    .iter()
                    .filter_map(|reexport| reexport.id())
                    .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did))
                    || self.tcx.is_doc_hidden(source_did);
```

created_at: 2025-03-03T16:45:20Z
author_association: MEMBER
diff_hunk: @@ -89,6 +88,25 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: ```suggestion
            if let Some(source_did) = source.did &&
                let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local())
            {
```

Let's avoid panicking if we can avoid it.
created_at: 2025-03-03T16:48:22Z
author_association: MEMBER
path: cg.dot
user: login: GuillaumeGomez
body: Please remove this file.
created_at: 2025-03-03T16:51:14Z
author_association: MEMBER
diff_hunk: @@ -89,6 +88,25 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did {
+                let import_def_id = i.def_id().unwrap().expect_local();
path: src/librustdoc/passes/strip_hidden.rs
user: login: xizheyin
body: Ok, I solved it.
created_at: 2025-03-03T16:51:36Z
author_association: MEMBER
diff_hunk: @@ -89,6 +88,26 @@ impl Stripper<'_, '_> {
 impl DocFolder for Stripper<'_, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
+
+        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind {
+            if let Some(source_did) = source.did
path: src/librustdoc/passes/strip_hidden.rs
user: login: GuillaumeGomez
body: ```suggestion
        if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
            && let Some(source_did) = source.did
```

Let's remove one indentation level too.
created_at: 2025-03-03T16:53:13Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,16 @@
+// Test for <https://github.com/rust-lang/rust/issues/137342>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ !has - '//*[@id="main-content"]//*[@class="struct"]' 'Bar'
+#[doc(hidden)]
+pub struct Bar;
+
+//@ !has - '//*' 'pub use crate::Bar as A;'
+pub use crate::Bar as A;
+//@ !has - '//*' 'pub use crate::A as B;'
+pub use crate::A as B;
+//@ has - '//dt/a[@class="struct"]' 'C'
path: tests/rustdoc/doc-hidden-source.rs
user: login: GuillaumeGomez
body: If I understood correctly, wasn't it supposed to generate `pub use crate::Bar as C;` instead of actually inlining?
created_at: 2025-03-03T17:42:27Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,16 @@
+// Test for <https://github.com/rust-lang/rust/issues/137342>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ !has - '//*[@id="main-content"]//*[@class="struct"]' 'Bar'
+#[doc(hidden)]
+pub struct Bar;
+
+//@ !has - '//*' 'pub use crate::Bar as A;'
+pub use crate::Bar as A;
+//@ !has - '//*' 'pub use crate::A as B;'
+pub use crate::A as B;
+//@ has - '//dt/a[@class="struct"]' 'C'
path: tests/rustdoc/doc-hidden-source.rs
user: login: xizheyin
body: c is regared as a non-reexport item in the beginning of the parsing. So it should be inline, to minimize the conflicts of the existing logic?
If we want to change the inline logic, maybe open another issue and PR is a good idea.
created_at: 2025-03-03T18:04:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,16 @@
+// Test for <https://github.com/rust-lang/rust/issues/137342>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ !has - '//*[@id="main-content"]//*[@class="struct"]' 'Bar'
+#[doc(hidden)]
+pub struct Bar;
+
+//@ !has - '//*' 'pub use crate::Bar as A;'
+pub use crate::Bar as A;
+//@ !has - '//*' 'pub use crate::A as B;'
+pub use crate::A as B;
+//@ has - '//dt/a[@class="struct"]' 'C'
path: tests/rustdoc/doc-hidden-source.rs
user: login: GuillaumeGomez
body: Fair enough.
created_at: 2025-03-03T22:04:03Z
author_association: MEMBER

PR comments:
user: login: rustbot
created_at: 2025-02-24T11:27:40Z
body: r? @notriddle

rustbot has assigned @notriddle.
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
author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-02-24T11:55:19Z
body: 
The job **`x86_64-gnu-llvm-18`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/13496949774/job/37706273982) [(plain)](https://github.com/rust-lang/rust/commit/5a93223d2849f590751bec025afa49a7d9cc628e/checks/37706273982/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
#21 exporting to docker image format
#21 sending tarball 28.1s done
#21 DONE 40.4s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Listening on address 127.0.0.1:4226
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
---- [rustdoc] tests/rustdoc/doc-hidden-reexports-109449.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/doc-hidden-reexports-109449" "/checkout/tests/rustdoc/doc-hidden-reexports-109449.rs"
--- stderr -------------------------------
29: count check failed
 Expected 4 occurrences but found 2
 Expected 4 occurrences but found 2
     //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 4
39: !has check failed
 `XPATH PATTERN` did not match
     //@ !has - '//*[@href="type.Yo.html"]' 'Yo'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
     //@ has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
42: !has check failed
 `XPATH PATTERN` did not match
     //@ !has - '//*[@href="struct.Yo2.html"]' 'Yo2'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
     //@ has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
49: !has check failed
     //@ !has 'foo/single_reexport/type.Yo.html'
50: !has check failed
     //@ !has 'foo/single_reexport/struct.Yo2.html'
 Expected 1 occurrences but found 2
 Expected 1 occurrences but found 2
     //@ count - '//dt' 1
Encountered 8 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/doc-hidden-crate.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/doc-hidden-crate" "/checkout/tests/rustdoc/doc-hidden-crate.rs"
--- stderr -------------------------------
12: !has check failed
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ !has - '//*' 'other'
13: !has check failed
 `XPATH PATTERN` did not match
 //@ !has - '//*' 'marker'
14: !has check failed
 `XPATH PATTERN` did not match
 //@ !has - '//*' 'PhantomData'
Encountered 3 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/files-creation-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/files-creation-hidden" "/checkout/tests/rustdoc/files-creation-hidden.rs"
--- stderr -------------------------------
--- stderr -------------------------------
3: Extra entries in folder `/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/files-creation-hidden/foo`: `{'struct.Baz.html', 'struct.Bar.html', 'bar', 'baz'}`
 //@ files foo '["index.html", "all.html", "sidebar-items.js"]'
3: files check failed
 //@ files foo '["index.html", "all.html", "sidebar-items.js"]'
8: !has check failed
 //@ !has "foo/struct.Bar.html"
11: !has check failed
 //@ !has "foo/struct.Baz.html"
19: !has check failed
 //@ !has "foo/bar/index.html"
22: !has check failed
 //@ !has "foo/baz/index.html"
Encountered 6 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/inline_local/hidden-use.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/inline_local/hidden-use" "/checkout/tests/rustdoc/inline_local/hidden-use.rs"
--- stderr -------------------------------
7: !hasraw check failed
 `PATTERN` did not match
 `PATTERN` did not match
 //@ !hasraw - 'Foo'
8: !has check failed
 //@ !has hidden_use/struct.Foo.html
Encountered 2 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-attr-merge.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-attr-merge" "/checkout/tests/rustdoc/reexport-attr-merge.rs"
--- stderr -------------------------------
21: count check failed
 Expected 2 occurrences but found 3
 Expected 2 occurrences but found 3
 //@ count - '//a[@class="struct"]' 2
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
Encountered 2 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-doc-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-doc-hidden" "/checkout/tests/rustdoc/reexport-doc-hidden.rs"
--- stderr -------------------------------
11: has check failed
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;'
Encountered 1 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-of-doc-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-of-doc-hidden" "/checkout/tests/rustdoc/reexport-of-doc-hidden.rs"
--- stderr -------------------------------
19: has check failed
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;'
Encountered 2 errors
------------------------------------------


```

</details>
        
author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-02-25T05:19:03Z
body: 
The job **`x86_64-gnu-llvm-18`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/13513905114/job/37759071010) [(plain)](https://github.com/rust-lang/rust/commit/9302da79f737f73a34f107c76922a29c44398586/checks/37759071010/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
#21 exporting to docker image format
#21 sending tarball 29.0s done
#21 DONE 37.9s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Listening on address 127.0.0.1:4226
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
---- [rustdoc] tests/rustdoc/doc-hidden-reexports-109449.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/doc-hidden-reexports-109449" "/checkout/tests/rustdoc/doc-hidden-reexports-109449.rs"
--- stderr -------------------------------
29: count check failed
 Expected 4 occurrences but found 2
 Expected 4 occurrences but found 2
     //@ count - '//*[@id="main-content"]/*[@class="item-table reexports"]//code' 4
39: !has check failed
 `XPATH PATTERN` did not match
     //@ !has - '//*[@href="type.Yo.html"]' 'Yo'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
     //@ has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
42: !has check failed
 `XPATH PATTERN` did not match
     //@ !has - '//*[@href="struct.Yo2.html"]' 'Yo2'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
     //@ has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
49: !has check failed
     //@ !has 'foo/single_reexport/type.Yo.html'
50: !has check failed
     //@ !has 'foo/single_reexport/struct.Yo2.html'
 Expected 1 occurrences but found 2
 Expected 1 occurrences but found 2
     //@ count - '//dt' 1
Encountered 8 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/files-creation-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/files-creation-hidden" "/checkout/tests/rustdoc/files-creation-hidden.rs"
--- stderr -------------------------------
--- stderr -------------------------------
3: Extra entries in folder `/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/files-creation-hidden/foo`: `{'bar', 'struct.Bar.html', 'struct.Baz.html', 'baz'}`
 //@ files foo '["index.html", "all.html", "sidebar-items.js"]'
3: files check failed
 //@ files foo '["index.html", "all.html", "sidebar-items.js"]'
8: !has check failed
 //@ !has "foo/struct.Bar.html"
11: !has check failed
 //@ !has "foo/struct.Baz.html"
19: !has check failed
 //@ !has "foo/bar/index.html"
22: !has check failed
 //@ !has "foo/baz/index.html"
Encountered 6 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/inline_local/hidden-use.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/inline_local/hidden-use" "/checkout/tests/rustdoc/inline_local/hidden-use.rs"
--- stderr -------------------------------
7: !hasraw check failed
 `PATTERN` did not match
 `PATTERN` did not match
 //@ !hasraw - 'Foo'
8: !has check failed
 //@ !has hidden_use/struct.Foo.html
Encountered 2 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-attr-merge.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-attr-merge" "/checkout/tests/rustdoc/reexport-attr-merge.rs"
--- stderr -------------------------------
21: count check failed
 Expected 2 occurrences but found 3
 Expected 2 occurrences but found 3
 //@ count - '//a[@class="struct"]' 2
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
Encountered 2 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-doc-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-doc-hidden" "/checkout/tests/rustdoc/reexport-doc-hidden.rs"
--- stderr -------------------------------
11: has check failed
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Type2"]/code' 'pub use crate::Type as Type2;'
Encountered 1 errors
------------------------------------------



---- [rustdoc] tests/rustdoc/reexport-of-doc-hidden.rs stdout ----

error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/reexport-of-doc-hidden" "/checkout/tests/rustdoc/reexport-of-doc-hidden.rs"
--- stderr -------------------------------
19: has check failed
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Boo"]/code' 'pub use crate::Bar as Boo;'
 `XPATH PATTERN` did not match
 `XPATH PATTERN` did not match
 //@ has - '//*[@id="reexport.Boo2"]/code' 'pub use crate::Bar as Boo2;'
Encountered 2 errors
------------------------------------------


```

</details>
        
author_association: COLLABORATOR
user: login: notriddle
created_at: 2025-02-25T21:00:53Z
body: 1. The :ghost: icon should never, ever appear unless you've passed `--document-hidden-items` to the CLI. The fact that a documented item's consumer-visible path is a re-export of a hidden item is an implementation detail and should not appear in the docs. Also, mystery meat icons should be avoided when the reader hasn't opted into them.

2. I've also found the spot where the decision was made to ignore re-exports of hidden items: https://github.com/rust-lang/rust/pull/109697#issuecomment-1551144464

   The problem, just to summarize, is caused by namespaces. You're allowed to do this:

   ```rust
   mod internals {
       pub type MyType = ();
       #[doc(hidden)] pub const MyType: () = ();
   }
   #[doc(inline)] pub use internals::MyType as MyType2;
   ```

   Presumably, you don't want the `const` to show up, only the type.

author_association: CONTRIBUTOR
user: login: xizheyin
created_at: 2025-02-26T13:24:31Z
body: Yeah, so as discussion [here](https://github.com/rust-lang/rust/issues/137342#issuecomment-2682589234), both `hidden_self_reexport` and `hidden_self_reexport_inline` shouldn't be visible.
author_association: MEMBER
user: login: xizheyin
created_at: 2025-02-27T13:00:08Z
body: r? @GuillaumeGomez 
author_association: MEMBER
user: login: xizheyin
created_at: 2025-03-01T12:43:43Z
body: This seems to work, is there anything else that needs to be changed? @GuillaumeGomez 
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-03T16:55:44Z
body: So finally, please add a new test checking that this code works as expected:

```rust
#[doc(hidden)]
pub struct Bar;

// Should not appear.
pub use crate::Bar as A;
// Should not appear.
pub use crate::A as B;
// Should appear under the form `pub use crate::Bar as B`.
#[doc(inline)]
pub use crate::Bar as C;
```
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-03T16:56:07Z
body: Ah and once the test is added, please [squash your commits](https://blog.guillaume-gomez.fr/Git-tips/1/2).
author_association: MEMBER
user: login: xizheyin
created_at: 2025-03-03T17:40:22Z
body: Ok, everything is done. @GuillaumeGomez 
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-03T22:04:45Z
body: Thanks!

@bors r+ rollup
author_association: MEMBER
user: login: bors
created_at: 2025-03-03T22:04:47Z
body: :pushpin: Commit 133705c402941c0825fe658a932289847478cf9f has been approved by `GuillaumeGomez`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust) for this repository.

<!-- @bors r=GuillaumeGomez 133705c402941c0825fe658a932289847478cf9f -->
<!-- homu: {"type":"Approved","sha":"133705c402941c0825fe658a932289847478cf9f","approver":"GuillaumeGomez","queue":"https://bors.rust-lang.org/homu/queue/rust"} -->
author_association: COLLABORATOR
user: login: compiler-errors
created_at: 2025-03-07T04:24:35Z
body: @rust-timer build 20f8c190f38f1aed347eae3d27e0f27bbc9508ff
author_association: CONTRIBUTOR
user: login: rust-timer
created_at: 2025-03-07T04:24:38Z
body: Queued 20f8c190f38f1aed347eae3d27e0f27bbc9508ff with parent b74da9613a8cb5ba67a985f71325be0b7b16c0dd, future [comparison URL](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff).
There are currently 0 preceding artifacts in the [queue](https://perf.rust-lang.org/status.html).
It will probably take at least ~1.3 hours until the benchmark run finishes.
<!-- rust-timer: temporary -->
author_association: COLLABORATOR
user: login: rust-timer
created_at: 2025-03-07T06:17:54Z
body: Finished benchmarking commit (20f8c190f38f1aed347eae3d27e0f27bbc9508ff): [comparison URL](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff&stat=instructions:u).

### Overall result: ❌ regressions - please read the text below


Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

**Next Steps**: If you can justify the regressions found in this try perf run, please indicate this with `@rustbot label: +perf-regression-triaged` along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression


### [Instruction count](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff&stat=instructions:u)
This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

|                                    | mean   | range            | count |
|:----------------------------------:|:------:|:----------------:|:-----:|
| Regressions ❌ <br /> (primary)    | -      | -                | 0     |
| Regressions ❌ <br /> (secondary)  | 167.7% | [167.7%, 167.7%] | 1     |
| Improvements ✅ <br /> (primary)   | -      | -                | 0     |
| Improvements ✅ <br /> (secondary) | -      | -                | 0     |
| All ❌✅ (primary)                 | -      | -                | 0     |

### [Max RSS (memory usage)](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff&stat=max-rss)
<details>
<summary>Results (primary -1.5%)</summary>

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

|                                    | mean  | range          | count |
|:----------------------------------:|:-----:|:--------------:|:-----:|
| Regressions ❌ <br /> (primary)    | -     | -              | 0     |
| Regressions ❌ <br /> (secondary)  | -     | -              | 0     |
| Improvements ✅ <br /> (primary)   | -1.5% | [-1.5%, -1.5%] | 1     |
| Improvements ✅ <br /> (secondary) | -     | -              | 0     |
| All ❌✅ (primary)                 | -1.5% | [-1.5%, -1.5%] | 1     |
</details>

### [Cycles](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff&stat=cycles:u)
<details>
<summary>Results (primary 1.3%, secondary 43.2%)</summary>

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

|                                    | mean  | range         | count |
|:----------------------------------:|:-----:|:-------------:|:-----:|
| Regressions ❌ <br /> (primary)    | 1.3%  | [0.7%, 2.5%]  | 3     |
| Regressions ❌ <br /> (secondary)  | 43.2% | [3.7%, 82.7%] | 2     |
| Improvements ✅ <br /> (primary)   | -     | -             | 0     |
| Improvements ✅ <br /> (secondary) | -     | -             | 0     |
| All ❌✅ (primary)                 | 1.3%  | [0.7%, 2.5%]  | 3     |
</details>

### [Binary size](https://perf.rust-lang.org/compare.html?start=b74da9613a8cb5ba67a985f71325be0b7b16c0dd&end=20f8c190f38f1aed347eae3d27e0f27bbc9508ff&stat=size:linked_artifact)
This benchmark run did not return any relevant results for this metric.

**Bootstrap**: 773.144s -> 773.568s (0.05%)
**Artifact size**: 362.14 MiB -> 362.17 MiB (0.01%)
author_association: COLLABORATOR
user: login: GuillaumeGomez
created_at: 2025-03-07T09:58:43Z
body: Wow, ok, gonna send a fix because it's way too bad.
author_association: MEMBER
user: login: xizheyin
created_at: 2025-03-07T10:10:38Z
body: It seems that traversing the list causes the complexity to change from o(n) to O (n²). Is there any better way? @GuillaumeGomez 
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-07T14:55:37Z
body: Not sure yet.
author_association: MEMBER
user: login: xizheyin
created_at: 2025-03-07T15:52:30Z
body: Do I need to restore it to the way it was before I submitted it?
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-07T16:01:43Z
body: No it's fine. The case where it's pretty terrible is made to check this case in particular. The problem here is more global. We should really rewrite how we strip hidden items because currently it's a mess.
author_association: MEMBER
user: login: GuillaumeGomez
created_at: 2025-03-07T16:15:02Z
body: I opened https://github.com/rust-lang/rust/issues/138168 to keep track of this work.
author_association: MEMBER
user: login: xizheyin
created_at: 2025-03-07T16:23:34Z
body: Yes, according to my observation, there may be problems when converting from ast to clean.
author_association: MEMBER
user: login: notriddle
created_at: 2025-03-07T16:42:02Z
body: Do you have an algorithm in mind that will do the correct thing without the performance problem?
author_association: CONTRIBUTOR
user: login: GuillaumeGomez
created_at: 2025-03-07T16:44:18Z
body: I think we should handle inlining and stripping at the same time. That would allow to make the conversion correctly based on the needs.
author_association: MEMBER