Auto merge of #114012 - GuillaumeGomez:fix-113982, r=notriddle
Fix missing attribute merge on glob foreign re-exports Fixes https://github.com/rust-lang/rust/issues/113982. The attributes were not merged with the import's in case of glob re-export of foreign items. r? `@notriddle`
This commit is contained in:
commit
6908c73ab0
@ -141,6 +141,7 @@ pub(crate) fn try_inline_glob(
|
|||||||
current_mod: LocalDefId,
|
current_mod: LocalDefId,
|
||||||
visited: &mut DefIdSet,
|
visited: &mut DefIdSet,
|
||||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
|
import: &hir::Item<'_>,
|
||||||
) -> Option<Vec<clean::Item>> {
|
) -> Option<Vec<clean::Item>> {
|
||||||
let did = res.opt_def_id()?;
|
let did = res.opt_def_id()?;
|
||||||
if did.is_local() {
|
if did.is_local() {
|
||||||
@ -158,7 +159,15 @@ pub(crate) fn try_inline_glob(
|
|||||||
.filter(|child| !child.reexport_chain.is_empty())
|
.filter(|child| !child.reexport_chain.is_empty())
|
||||||
.filter_map(|child| child.res.opt_def_id())
|
.filter_map(|child| child.res.opt_def_id())
|
||||||
.collect();
|
.collect();
|
||||||
let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports));
|
let attrs = cx.tcx.hir().attrs(import.hir_id());
|
||||||
|
let mut items = build_module_items(
|
||||||
|
cx,
|
||||||
|
did,
|
||||||
|
visited,
|
||||||
|
inlined_names,
|
||||||
|
Some(&reexports),
|
||||||
|
Some((attrs, Some(import.owner_id.def_id.to_def_id()))),
|
||||||
|
);
|
||||||
items.retain(|item| {
|
items.retain(|item| {
|
||||||
if let Some(name) = item.name {
|
if let Some(name) = item.name {
|
||||||
// If an item with the same type and name already exists,
|
// If an item with the same type and name already exists,
|
||||||
@ -549,7 +558,7 @@ pub(crate) fn build_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module {
|
fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module {
|
||||||
let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None);
|
let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None, None);
|
||||||
|
|
||||||
let span = clean::Span::new(cx.tcx.def_span(did));
|
let span = clean::Span::new(cx.tcx.def_span(did));
|
||||||
clean::Module { items, span }
|
clean::Module { items, span }
|
||||||
@ -561,6 +570,7 @@ fn build_module_items(
|
|||||||
visited: &mut DefIdSet,
|
visited: &mut DefIdSet,
|
||||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
allowed_def_ids: Option<&DefIdSet>,
|
allowed_def_ids: Option<&DefIdSet>,
|
||||||
|
attrs: Option<(&[ast::Attribute], Option<DefId>)>,
|
||||||
) -> Vec<clean::Item> {
|
) -> Vec<clean::Item> {
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
@ -615,7 +625,7 @@ fn build_module_items(
|
|||||||
cfg: None,
|
cfg: None,
|
||||||
inline_stmt_id: None,
|
inline_stmt_id: None,
|
||||||
});
|
});
|
||||||
} else if let Some(i) = try_inline(cx, res, item.ident.name, None, visited) {
|
} else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
|
||||||
items.extend(i)
|
items.extend(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,25 +132,31 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
|||||||
});
|
});
|
||||||
|
|
||||||
let kind = ModuleItem(Module { items, span });
|
let kind = ModuleItem(Module { items, span });
|
||||||
generate_item_with_correct_attrs(cx, kind, doc.def_id, doc.name, doc.import_id, doc.renamed)
|
generate_item_with_correct_attrs(
|
||||||
|
cx,
|
||||||
|
kind,
|
||||||
|
doc.def_id.to_def_id(),
|
||||||
|
doc.name,
|
||||||
|
doc.import_id,
|
||||||
|
doc.renamed,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_item_with_correct_attrs(
|
fn generate_item_with_correct_attrs(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
kind: ItemKind,
|
kind: ItemKind,
|
||||||
local_def_id: LocalDefId,
|
def_id: DefId,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
import_id: Option<LocalDefId>,
|
import_id: Option<LocalDefId>,
|
||||||
renamed: Option<Symbol>,
|
renamed: Option<Symbol>,
|
||||||
) -> Item {
|
) -> Item {
|
||||||
let def_id = local_def_id.to_def_id();
|
|
||||||
let target_attrs = inline::load_attrs(cx, def_id);
|
let target_attrs = inline::load_attrs(cx, def_id);
|
||||||
let attrs = if let Some(import_id) = import_id {
|
let attrs = if let Some(import_id) = import_id {
|
||||||
let is_inline = inline::load_attrs(cx, import_id.to_def_id())
|
let is_inline = inline::load_attrs(cx, import_id.to_def_id())
|
||||||
.lists(sym::doc)
|
.lists(sym::doc)
|
||||||
.get_word_attr(sym::inline)
|
.get_word_attr(sym::inline)
|
||||||
.is_some();
|
.is_some();
|
||||||
let mut attrs = get_all_import_attributes(cx, import_id, local_def_id, is_inline);
|
let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline);
|
||||||
add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
|
add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
|
||||||
attrs
|
attrs
|
||||||
} else {
|
} else {
|
||||||
@ -2308,10 +2314,10 @@ fn clean_bare_fn_ty<'tcx>(
|
|||||||
pub(crate) fn reexport_chain<'tcx>(
|
pub(crate) fn reexport_chain<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
import_def_id: LocalDefId,
|
import_def_id: LocalDefId,
|
||||||
target_def_id: LocalDefId,
|
target_def_id: DefId,
|
||||||
) -> &'tcx [Reexport] {
|
) -> &'tcx [Reexport] {
|
||||||
for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
|
for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
|
||||||
if child.res.opt_def_id() == Some(target_def_id.to_def_id())
|
if child.res.opt_def_id() == Some(target_def_id)
|
||||||
&& child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
|
&& child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
|
||||||
{
|
{
|
||||||
return &child.reexport_chain;
|
return &child.reexport_chain;
|
||||||
@ -2324,7 +2330,7 @@ pub(crate) fn reexport_chain<'tcx>(
|
|||||||
fn get_all_import_attributes<'hir>(
|
fn get_all_import_attributes<'hir>(
|
||||||
cx: &mut DocContext<'hir>,
|
cx: &mut DocContext<'hir>,
|
||||||
import_def_id: LocalDefId,
|
import_def_id: LocalDefId,
|
||||||
target_def_id: LocalDefId,
|
target_def_id: DefId,
|
||||||
is_inline: bool,
|
is_inline: bool,
|
||||||
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
|
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
|
||||||
let mut attrs = Vec::new();
|
let mut attrs = Vec::new();
|
||||||
@ -2541,7 +2547,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
vec![generate_item_with_correct_attrs(
|
vec![generate_item_with_correct_attrs(
|
||||||
cx,
|
cx,
|
||||||
kind,
|
kind,
|
||||||
item.owner_id.def_id,
|
item.owner_id.def_id.to_def_id(),
|
||||||
name,
|
name,
|
||||||
import_id,
|
import_id,
|
||||||
renamed,
|
renamed,
|
||||||
@ -2691,6 +2697,7 @@ fn clean_use_statement_inner<'tcx>(
|
|||||||
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
|
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
|
||||||
let pub_underscore = visibility.is_public() && name == kw::Underscore;
|
let pub_underscore = visibility.is_public() && name == kw::Underscore;
|
||||||
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
|
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
|
||||||
|
let import_def_id = import.owner_id.def_id.to_def_id();
|
||||||
|
|
||||||
// The parent of the module in which this import resides. This
|
// The parent of the module in which this import resides. This
|
||||||
// is the same as `current_mod` if that's already the top
|
// is the same as `current_mod` if that's already the top
|
||||||
@ -2741,9 +2748,14 @@ fn clean_use_statement_inner<'tcx>(
|
|||||||
let inner = if kind == hir::UseKind::Glob {
|
let inner = if kind == hir::UseKind::Glob {
|
||||||
if !denied {
|
if !denied {
|
||||||
let mut visited = DefIdSet::default();
|
let mut visited = DefIdSet::default();
|
||||||
if let Some(items) =
|
if let Some(items) = inline::try_inline_glob(
|
||||||
inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names)
|
cx,
|
||||||
{
|
path.res,
|
||||||
|
current_mod,
|
||||||
|
&mut visited,
|
||||||
|
inlined_names,
|
||||||
|
import,
|
||||||
|
) {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2759,7 +2771,6 @@ fn clean_use_statement_inner<'tcx>(
|
|||||||
denied = true;
|
denied = true;
|
||||||
}
|
}
|
||||||
if !denied {
|
if !denied {
|
||||||
let import_def_id = import.owner_id.to_def_id();
|
|
||||||
if let Some(mut items) = inline::try_inline(
|
if let Some(mut items) = inline::try_inline(
|
||||||
cx,
|
cx,
|
||||||
path.res,
|
path.res,
|
||||||
@ -2779,7 +2790,7 @@ fn clean_use_statement_inner<'tcx>(
|
|||||||
Import::new_simple(name, resolve_use_source(cx, path), true)
|
Import::new_simple(name, resolve_use_source(cx, path), true)
|
||||||
};
|
};
|
||||||
|
|
||||||
vec![Item::from_def_id_and_parts(import.owner_id.to_def_id(), None, ImportItem(inner), cx)]
|
vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_maybe_renamed_foreign_item<'tcx>(
|
fn clean_maybe_renamed_foreign_item<'tcx>(
|
||||||
|
@ -282,7 +282,7 @@ fn maybe_inline_local(
|
|||||||
// made reachable by cross-crate inlining which we're checking here.
|
// made reachable by cross-crate inlining which we're checking here.
|
||||||
// (this is done here because we need to know this upfront).
|
// (this is done here because we need to know this upfront).
|
||||||
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
|
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
|
||||||
if is_hidden {
|
if is_hidden || glob {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// We store inlined foreign items otherwise, it'd mean that the `use` item would be kept
|
// We store inlined foreign items otherwise, it'd mean that the `use` item would be kept
|
||||||
@ -376,7 +376,7 @@ fn reexport_public_and_not_hidden(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let tcx = self.cx.tcx;
|
let tcx = self.cx.tcx;
|
||||||
let item_def_id = reexport_chain(tcx, import_def_id, target_def_id)
|
let item_def_id = reexport_chain(tcx, import_def_id, target_def_id.to_def_id())
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|reexport| reexport.id())
|
.flat_map(|reexport| reexport.id())
|
||||||
.map(|id| id.expect_local())
|
.map(|id| id.expect_local())
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
#![crate_name = "colors"]
|
||||||
|
|
||||||
|
pub struct Color;
|
19
tests/rustdoc/issue-113982-doc_auto_cfg-reexport-foreign.rs
Normal file
19
tests/rustdoc/issue-113982-doc_auto_cfg-reexport-foreign.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// aux-build: issue-113982-doc_auto_cfg-reexport-foreign.rs
|
||||||
|
|
||||||
|
#![feature(no_core, doc_auto_cfg)]
|
||||||
|
#![no_core]
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
extern crate colors;
|
||||||
|
|
||||||
|
// @has 'foo/index.html' '//*[@class="stab portability"]' 'Non-colors'
|
||||||
|
// @has 'foo/struct.Color.html' '//*[@class="stab portability"]' \
|
||||||
|
// 'Available on non-crate feature colors only.'
|
||||||
|
#[cfg(not(feature = "colors"))]
|
||||||
|
pub use colors::*;
|
||||||
|
|
||||||
|
// @has 'foo/index.html' '//*[@class="stab portability"]' 'Non-fruits'
|
||||||
|
// @has 'foo/struct.Red.html' '//*[@class="stab portability"]' \
|
||||||
|
// 'Available on non-crate feature fruits only.'
|
||||||
|
#[cfg(not(feature = "fruits"))]
|
||||||
|
pub use colors::Color as Red;
|
Loading…
Reference in New Issue
Block a user