diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c6939326144ea..b3b0933123349 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -9,7 +9,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::{self, TyCtxt}; @@ -162,6 +162,7 @@ pub(crate) fn try_inline( pub(crate) fn try_inline_glob( cx: &mut DocContext<'_>, res: Res, + current_mod: LocalDefId, visited: &mut FxHashSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, ) -> Option> { @@ -172,7 +173,16 @@ pub(crate) fn try_inline_glob( match res { Res::Def(DefKind::Mod, did) => { - let mut items = build_module_items(cx, did, visited, inlined_names); + // Use the set of module reexports to filter away names that are not actually + // reexported by the glob, e.g. because they are shadowed by something else. + let reexports = cx + .tcx + .module_reexports(current_mod) + .unwrap_or_default() + .iter() + .filter_map(|child| child.res.opt_def_id()) + .collect(); + let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports)); items.drain_filter(|item| { if let Some(name) = item.name { // If an item with the same type and name already exists, @@ -563,7 +573,7 @@ fn build_module( did: DefId, visited: &mut FxHashSet, ) -> clean::Module { - let items = build_module_items(cx, did, visited, &mut FxHashSet::default()); + let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None); let span = clean::Span::new(cx.tcx.def_span(did)); clean::Module { items, span } @@ -574,6 +584,7 @@ fn build_module_items( did: DefId, visited: &mut FxHashSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, + allowed_def_ids: Option<&FxHashSet>, ) -> Vec { let mut items = Vec::new(); @@ -583,6 +594,11 @@ fn build_module_items( for &item in cx.tcx.module_children(did).iter() { if item.vis.is_public() { let res = item.res.expect_non_local(); + if let Some(def_id) = res.opt_def_id() + && let Some(allowed_def_ids) = allowed_def_ids + && !allowed_def_ids.contains(&def_id) { + continue; + } if let Some(def_id) = res.mod_def_id() { // If we're inlining a glob import, it's possible to have // two distinct modules with the same name. We don't want to diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 415e7d5a360d0..20984696b6c01 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2441,7 +2441,8 @@ fn clean_use_statement_inner<'tcx>( let inner = if kind == hir::UseKind::Glob { if !denied { let mut visited = FxHashSet::default(); - if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited, inlined_names) + if let Some(items) = + inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names) { return items; } diff --git a/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs b/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs index cde7f68ff0182..48672590a12dd 100644 --- a/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs +++ b/tests/rustdoc/inline_cross/auxiliary/cross-glob.rs @@ -3,3 +3,5 @@ pub struct SomeStruct; pub fn some_fn() {} + +pub enum Shadowed {} diff --git a/tests/rustdoc/inline_cross/cross-glob.rs b/tests/rustdoc/inline_cross/cross-glob.rs index f97da11a90149..7a519d2d25547 100644 --- a/tests/rustdoc/inline_cross/cross-glob.rs +++ b/tests/rustdoc/inline_cross/cross-glob.rs @@ -6,6 +6,11 @@ extern crate inner; // @has cross_glob/struct.SomeStruct.html // @has cross_glob/fn.some_fn.html +// @!has cross_glob/enum.Shadowed.html // @!has cross_glob/index.html '//code' 'pub use inner::*;' #[doc(inline)] pub use inner::*; + +// This type shadows the glob-imported enum `Shadowed`. +// @has cross_glob/type.Shadowed.html +pub type Shadowed = u8;