Skip to content

Commit

Permalink
Auto merge of rust-lang#106952 - petrochenkov:docglob, r=notriddle,Gu…
Browse files Browse the repository at this point in the history
…illaumeGomez

rustdoc: Fix glob import inlining

Filter away names that are not actually imported by the glob, e.g. because they are shadowed by something else.

Fixes the issue found in rust-lang#94857 (comment).
  • Loading branch information
bors committed Jan 18, 2023
2 parents e08b379 + 3b0d306 commit aaa9bb9
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 4 deletions.
22 changes: 19 additions & 3 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<DefId>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Option<Vec<clean::Item>> {
Expand All @@ -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,
Expand Down Expand Up @@ -563,7 +573,7 @@ fn build_module(
did: DefId,
visited: &mut FxHashSet<DefId>,
) -> 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 }
Expand All @@ -574,6 +584,7 @@ fn build_module_items(
did: DefId,
visited: &mut FxHashSet<DefId>,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
allowed_def_ids: Option<&FxHashSet<DefId>>,
) -> Vec<clean::Item> {
let mut items = Vec::new();

Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions tests/rustdoc/inline_cross/auxiliary/cross-glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
pub struct SomeStruct;

pub fn some_fn() {}

pub enum Shadowed {}
5 changes: 5 additions & 0 deletions tests/rustdoc/inline_cross/cross-glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

0 comments on commit aaa9bb9

Please sign in to comment.