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
This commit is contained in:
parent
481725984b
commit
3b0d306b94
@ -9,7 +9,7 @@
|
||||
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<DefId>,
|
||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||
) -> Option<Vec<clean::Item>> {
|
||||
@ -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<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 }
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -3,3 +3,5 @@
|
||||
pub struct SomeStruct;
|
||||
|
||||
pub fn some_fn() {}
|
||||
|
||||
pub enum Shadowed {}
|
||||
|
@ -6,6 +6,11 @@
|
||||
|
||||
// @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;
|
||||
|
Loading…
Reference in New Issue
Block a user