diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2c98cba90d718..25d224b9a7337 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -57,11 +57,43 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> { .map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)), ); items.extend(self.mods.iter().map(|x| x.clean(cx))); - items.extend( - self.items - .iter() - .flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)), - ); + + // Split up imports from all other items. + // + // This covers the case where somebody does an import which should pull in an item, + // but there's already an item with the same namespace and same name. Rust gives + // priority to the not-imported one, so we should, too. + let mut inserted = FxHashSet::default(); + items.extend(self.items.iter().flat_map(|(item, renamed)| { + // First, lower everything other than imports. + if matches!(item.kind, hir::ItemKind::Use(..)) { + return Vec::new(); + } + let v = clean_maybe_renamed_item(cx, item, *renamed); + for item in &v { + if let Some(name) = item.name { + inserted.insert((item.type_(), name)); + } + } + v + })); + items.extend(self.items.iter().flat_map(|(item, renamed)| { + // Now we actually lower the imports, skipping everything else. + if !matches!(item.kind, hir::ItemKind::Use(..)) { + return Vec::new(); + } + let mut v = clean_maybe_renamed_item(cx, item, *renamed); + v.drain_filter(|item| { + if let Some(name) = item.name { + // If an item with the same type and name already exists, + // it takes priority over the inlined stuff. + !inserted.insert((item.type_(), name)) + } else { + false + } + }); + v + })); // determine if we should display the inner contents or // the outer `mod` item for the source code. diff --git a/src/test/rustdoc/auxiliary/issue-99221-aux.rs b/src/test/rustdoc/auxiliary/issue-99221-aux.rs new file mode 100644 index 0000000000000..e061e42b29db8 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-99221-aux.rs @@ -0,0 +1,20 @@ +pub struct Option; +impl Option { + pub fn unwrap(self) {} +} + +mod macros { + use crate::Option; + /// [`Option::unwrap`] + #[macro_export] + macro_rules! print { + () => () + } +} + +mod structs { + use crate::Option; + /// [`Option::unwrap`] + pub struct Print; +} +pub use structs::Print; diff --git a/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs b/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs new file mode 100644 index 0000000000000..e74881d387dc1 --- /dev/null +++ b/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name-submodule.rs @@ -0,0 +1,19 @@ +// aux-build:issue-99221-aux.rs +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "foo"] + +#[macro_use] +extern crate issue_99221_aux; + +pub use issue_99221_aux::*; + +// @count foo/index.html '//a[@class="macro"]' 1 + +mod inner { + #[macro_export] + macro_rules! print { + () => () + } +} diff --git a/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs b/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs new file mode 100644 index 0000000000000..46d59654b99eb --- /dev/null +++ b/src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs @@ -0,0 +1,17 @@ +// aux-build:issue-99221-aux.rs +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "foo"] + +#[macro_use] +extern crate issue_99221_aux; + +pub use issue_99221_aux::*; + +// @count foo/index.html '//a[@class="macro"]' 1 + +#[macro_export] +macro_rules! print { + () => () +} diff --git a/src/test/rustdoc/issue-99221-multiple-structs-w-same-name.rs b/src/test/rustdoc/issue-99221-multiple-structs-w-same-name.rs new file mode 100644 index 0000000000000..41e64726a3246 --- /dev/null +++ b/src/test/rustdoc/issue-99221-multiple-structs-w-same-name.rs @@ -0,0 +1,14 @@ +// aux-build:issue-99221-aux.rs +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "foo"] + +#[macro_use] +extern crate issue_99221_aux; + +pub use issue_99221_aux::*; + +// @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1 + +pub struct Print;