about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-09-10 18:56:09 +0530
committerGitHub <noreply@github.com>2022-09-10 18:56:09 +0530
commit6afbe3eca92da175a197cdd3d75cf9c623bf53eb (patch)
treeeaf4c9d7abde9b9787aad0b782ced4697d03a2c8 /src/librustdoc
parentf1412a665f6c3f04fba0f192d9de4c12d823f9f3 (diff)
parentd92d642707c845b88a0618135ad993723a30c7e2 (diff)
Rollup merge of #101631 - rust-lang:notriddle/duplicate-module, r=GuillaumeGomez
rustdoc: avoid cleaning modules with duplicate names

Fixes #83375
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/mod.rs19
-rw-r--r--src/librustdoc/visit_ast.rs12
2 files changed, 26 insertions, 5 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 08b696e65eb..bca3f4db4a8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -50,14 +50,23 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     let mut inserted = FxHashSet::default();
     items.extend(doc.foreigns.iter().map(|(item, renamed)| {
         let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
-        if let Some(name) = item.name {
+        if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
             inserted.insert((item.type_(), name));
         }
         item
     }));
-    items.extend(doc.mods.iter().map(|x| {
-        inserted.insert((ItemType::Module, x.name));
-        clean_doc_module(x, cx)
+    items.extend(doc.mods.iter().filter_map(|x| {
+        if !inserted.insert((ItemType::Module, x.name)) {
+            return None;
+        }
+        let item = clean_doc_module(x, cx);
+        if item.attrs.lists(sym::doc).has_word(sym::hidden) {
+            // Hidden modules are stripped at a later stage.
+            // If a hidden module has the same name as a visible one, we want
+            // to keep both of them around.
+            inserted.remove(&(ItemType::Module, x.name));
+        }
+        Some(item)
     }));
 
     // Split up imports from all other items.
@@ -72,7 +81,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
         }
         let v = clean_maybe_renamed_item(cx, item, *renamed);
         for item in &v {
-            if let Some(name) = item.name {
+            if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
                 inserted.insert((item.type_(), name));
             }
         }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ca7a20bf368..c27ac0ac40e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -164,8 +164,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
+            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                continue;
+            }
             self.visit_item(item, None, &mut om);
         }
+        for &i in m.item_ids {
+            let item = self.cx.tcx.hir().item(i);
+            // To match the way import precedence works, visit glob imports last.
+            // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
+            // imported items appear last, then they'll be the ones that get discarded.
+            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                self.visit_item(item, None, &mut om);
+            }
+        }
         self.inside_public_path = orig_inside_public_path;
         om
     }