Skip to content

Commit b3e6cbb

Browse files
authored
Rollup merge of rust-lang#109312 - petrochenkov:docice5, r=GuillaumeGomez
rustdoc: Cleanup parent module tracking for doc links Keep ids of the documented items themselves, not their parent modules. Parent modules can be retreived from those ids when necessary. Fixes rust-lang#108501. That issue could be fixed in a more local way, but this refactoring is something that I wanted to do since rust-lang#93805 anyway.
2 parents 46a3442 + 0f45d85 commit b3e6cbb

File tree

10 files changed

+123
-185
lines changed

10 files changed

+123
-185
lines changed

compiler/rustc_resolve/src/rustdoc.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ pub enum DocFragmentKind {
2626
#[derive(Clone, PartialEq, Eq, Debug)]
2727
pub struct DocFragment {
2828
pub span: Span,
29-
/// The module this doc-comment came from.
30-
///
31-
/// This allows distinguishing between the original documentation and a pub re-export.
32-
/// If it is `None`, the item was not re-exported.
33-
pub parent_module: Option<DefId>,
29+
/// The item this doc-comment came from.
30+
/// Used to determine the scope in which doc links in this fragment are resolved.
31+
/// Typically filled for reexport docs when they are merged into the docs of the
32+
/// original reexported item.
33+
/// If the id is not filled, which happens for the original reexported item, then
34+
/// it has to be taken from somewhere else during doc link resolution.
35+
pub item_id: Option<DefId>,
3436
pub doc: Symbol,
3537
pub kind: DocFragmentKind,
3638
pub indent: usize,
@@ -186,15 +188,15 @@ pub fn attrs_to_doc_fragments<'a>(
186188
) -> (Vec<DocFragment>, ast::AttrVec) {
187189
let mut doc_fragments = Vec::new();
188190
let mut other_attrs = ast::AttrVec::new();
189-
for (attr, parent_module) in attrs {
191+
for (attr, item_id) in attrs {
190192
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
191193
let doc = beautify_doc_string(doc_str, comment_kind);
192194
let kind = if attr.is_doc_comment() {
193195
DocFragmentKind::SugaredDoc
194196
} else {
195197
DocFragmentKind::RawDoc
196198
};
197-
let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
199+
let fragment = DocFragment { span: attr.span, doc, kind, item_id, indent: 0 };
198200
doc_fragments.push(fragment);
199201
} else if !doc_only {
200202
other_attrs.push(attr.clone());
@@ -216,7 +218,7 @@ pub fn prepare_to_doc_link_resolution(
216218
) -> FxHashMap<Option<DefId>, String> {
217219
let mut res = FxHashMap::default();
218220
for fragment in doc_fragments {
219-
let out_str = res.entry(fragment.parent_module).or_default();
221+
let out_str = res.entry(fragment.item_id).or_default();
220222
add_doc_fragment(out_str, fragment);
221223
}
222224
res

src/librustdoc/clean/inline.rs

+23-52
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,11 @@ use crate::formats::item_type::ItemType;
3636
///
3737
/// The returned value is `None` if the definition could not be inlined,
3838
/// and `Some` of a vector of items if it was successfully expanded.
39-
///
40-
/// `parent_module` refers to the parent of the *re-export*, not the original item.
4139
pub(crate) fn try_inline(
4240
cx: &mut DocContext<'_>,
43-
parent_module: DefId,
44-
import_def_id: Option<DefId>,
4541
res: Res,
4642
name: Symbol,
47-
attrs: Option<&[ast::Attribute]>,
43+
attrs: Option<(&[ast::Attribute], Option<DefId>)>,
4844
visited: &mut DefIdSet,
4945
) -> Option<Vec<clean::Item>> {
5046
let did = res.opt_def_id()?;
@@ -55,38 +51,17 @@ pub(crate) fn try_inline(
5551

5652
debug!("attrs={:?}", attrs);
5753

58-
let attrs_without_docs = attrs.map(|attrs| {
59-
attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>()
54+
let attrs_without_docs = attrs.map(|(attrs, def_id)| {
55+
(attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
6056
});
61-
// We need this ugly code because:
62-
//
63-
// ```
64-
// attrs_without_docs.map(|a| a.as_slice())
65-
// ```
66-
//
67-
// will fail because it returns a temporary slice and:
68-
//
69-
// ```
70-
// attrs_without_docs.map(|s| {
71-
// vec = s.as_slice();
72-
// vec
73-
// })
74-
// ```
75-
//
76-
// will fail because we're moving an uninitialized variable into a closure.
77-
let vec;
78-
let attrs_without_docs = match attrs_without_docs {
79-
Some(s) => {
80-
vec = s;
81-
Some(vec.as_slice())
82-
}
83-
None => None,
84-
};
57+
let attrs_without_docs =
58+
attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));
8559

60+
let import_def_id = attrs.and_then(|(_, def_id)| def_id);
8661
let kind = match res {
8762
Res::Def(DefKind::Trait, did) => {
8863
record_extern_fqn(cx, did, ItemType::Trait);
89-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
64+
build_impls(cx, did, attrs_without_docs, &mut ret);
9065
clean::TraitItem(Box::new(build_external_trait(cx, did)))
9166
}
9267
Res::Def(DefKind::Fn, did) => {
@@ -95,27 +70,27 @@ pub(crate) fn try_inline(
9570
}
9671
Res::Def(DefKind::Struct, did) => {
9772
record_extern_fqn(cx, did, ItemType::Struct);
98-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
73+
build_impls(cx, did, attrs_without_docs, &mut ret);
9974
clean::StructItem(build_struct(cx, did))
10075
}
10176
Res::Def(DefKind::Union, did) => {
10277
record_extern_fqn(cx, did, ItemType::Union);
103-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
78+
build_impls(cx, did, attrs_without_docs, &mut ret);
10479
clean::UnionItem(build_union(cx, did))
10580
}
10681
Res::Def(DefKind::TyAlias, did) => {
10782
record_extern_fqn(cx, did, ItemType::Typedef);
108-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
83+
build_impls(cx, did, attrs_without_docs, &mut ret);
10984
clean::TypedefItem(build_type_alias(cx, did))
11085
}
11186
Res::Def(DefKind::Enum, did) => {
11287
record_extern_fqn(cx, did, ItemType::Enum);
113-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
88+
build_impls(cx, did, attrs_without_docs, &mut ret);
11489
clean::EnumItem(build_enum(cx, did))
11590
}
11691
Res::Def(DefKind::ForeignTy, did) => {
11792
record_extern_fqn(cx, did, ItemType::ForeignType);
118-
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
93+
build_impls(cx, did, attrs_without_docs, &mut ret);
11994
clean::ForeignTypeItem
12095
}
12196
// Never inline enum variants but leave them shown as re-exports.
@@ -149,7 +124,7 @@ pub(crate) fn try_inline(
149124
_ => return None,
150125
};
151126

152-
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs);
127+
let (attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
153128
cx.inlined.insert(did.into());
154129
let mut item =
155130
clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, Box::new(attrs), cfg);
@@ -316,17 +291,16 @@ fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef>
316291
/// Builds all inherent implementations of an ADT (struct/union/enum) or Trait item/path/reexport.
317292
pub(crate) fn build_impls(
318293
cx: &mut DocContext<'_>,
319-
parent_module: Option<DefId>,
320294
did: DefId,
321-
attrs: Option<&[ast::Attribute]>,
295+
attrs: Option<(&[ast::Attribute], Option<DefId>)>,
322296
ret: &mut Vec<clean::Item>,
323297
) {
324298
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
325299
let tcx = cx.tcx;
326300

327301
// for each implementation of an item represented by `did`, build the clean::Item for that impl
328302
for &did in tcx.inherent_impls(did).iter() {
329-
build_impl(cx, parent_module, did, attrs, ret);
303+
build_impl(cx, did, attrs, ret);
330304
}
331305

332306
// This pretty much exists expressly for `dyn Error` traits that exist in the `alloc` crate.
@@ -340,28 +314,26 @@ pub(crate) fn build_impls(
340314
let type_ =
341315
if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
342316
for &did in tcx.incoherent_impls(type_) {
343-
build_impl(cx, parent_module, did, attrs, ret);
317+
build_impl(cx, did, attrs, ret);
344318
}
345319
}
346320
}
347321

348-
/// `parent_module` refers to the parent of the re-export, not the original item
349322
pub(crate) fn merge_attrs(
350323
cx: &mut DocContext<'_>,
351-
parent_module: Option<DefId>,
352324
old_attrs: &[ast::Attribute],
353-
new_attrs: Option<&[ast::Attribute]>,
325+
new_attrs: Option<(&[ast::Attribute], Option<DefId>)>,
354326
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
355327
// NOTE: If we have additional attributes (from a re-export),
356328
// always insert them first. This ensure that re-export
357329
// doc comments show up before the original doc comments
358330
// when we render them.
359-
if let Some(inner) = new_attrs {
331+
if let Some((inner, item_id)) = new_attrs {
360332
let mut both = inner.to_vec();
361333
both.extend_from_slice(old_attrs);
362334
(
363-
if let Some(new_id) = parent_module {
364-
Attributes::from_ast_with_additional(old_attrs, (inner, new_id))
335+
if let Some(item_id) = item_id {
336+
Attributes::from_ast_with_additional(old_attrs, (inner, item_id))
365337
} else {
366338
Attributes::from_ast(&both)
367339
},
@@ -375,9 +347,8 @@ pub(crate) fn merge_attrs(
375347
/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`.
376348
pub(crate) fn build_impl(
377349
cx: &mut DocContext<'_>,
378-
parent_module: Option<DefId>,
379350
did: DefId,
380-
attrs: Option<&[ast::Attribute]>,
351+
attrs: Option<(&[ast::Attribute], Option<DefId>)>,
381352
ret: &mut Vec<clean::Item>,
382353
) {
383354
if !cx.inlined.insert(did.into()) {
@@ -539,7 +510,7 @@ pub(crate) fn build_impl(
539510
record_extern_trait(cx, did);
540511
}
541512

542-
let (merged_attrs, cfg) = merge_attrs(cx, parent_module, load_attrs(cx, did), attrs);
513+
let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
543514
trace!("merged_attrs={:?}", merged_attrs);
544515

545516
trace!(
@@ -635,7 +606,7 @@ fn build_module_items(
635606
cfg: None,
636607
inline_stmt_id: None,
637608
});
638-
} else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
609+
} else if let Some(i) = try_inline(cx, res, item.ident.name, None, visited) {
639610
items.extend(i)
640611
}
641612
}

src/librustdoc/clean/mod.rs

+8-18
Original file line numberDiff line numberDiff line change
@@ -2388,12 +2388,12 @@ fn clean_maybe_renamed_item<'tcx>(
23882388
target_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
23892389
}
23902390

2391-
let import_parent = import_id.map(|import_id| cx.tcx.local_parent(import_id).to_def_id());
2392-
let (attrs, cfg) = merge_attrs(cx, import_parent, &target_attrs, Some(&import_attrs));
2391+
let import_id = import_id.map(|def_id| def_id.to_def_id());
2392+
let (attrs, cfg) = merge_attrs(cx, &target_attrs, Some((&import_attrs, import_id)));
23932393

23942394
let mut item =
23952395
Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);
2396-
item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
2396+
item.inline_stmt_id = import_id;
23972397
vec![item]
23982398
})
23992399
}
@@ -2478,18 +2478,12 @@ fn clean_extern_crate<'tcx>(
24782478

24792479
let krate_owner_def_id = krate.owner_id.to_def_id();
24802480
if please_inline {
2481-
let mut visited = DefIdSet::default();
2482-
2483-
let res = Res::Def(DefKind::Mod, crate_def_id);
2484-
24852481
if let Some(items) = inline::try_inline(
24862482
cx,
2487-
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
2488-
Some(krate_owner_def_id),
2489-
res,
2483+
Res::Def(DefKind::Mod, crate_def_id),
24902484
name,
2491-
Some(attrs),
2492-
&mut visited,
2485+
Some((attrs, Some(krate_owner_def_id))),
2486+
&mut Default::default(),
24932487
) {
24942488
return items;
24952489
}
@@ -2613,17 +2607,13 @@ fn clean_use_statement_inner<'tcx>(
26132607
denied = true;
26142608
}
26152609
if !denied {
2616-
let mut visited = DefIdSet::default();
26172610
let import_def_id = import.owner_id.to_def_id();
2618-
26192611
if let Some(mut items) = inline::try_inline(
26202612
cx,
2621-
cx.tcx.parent_module(import.hir_id()).to_def_id(),
2622-
Some(import_def_id),
26232613
path.res,
26242614
name,
2625-
Some(attrs),
2626-
&mut visited,
2615+
Some((attrs, Some(import_def_id))),
2616+
&mut Default::default(),
26272617
) {
26282618
items.push(Item::from_def_id_and_parts(
26292619
import_def_id,

src/librustdoc/clean/types/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_span::symbol::Symbol;
1010
fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
1111
vec![DocFragment {
1212
span: DUMMY_SP,
13-
parent_module: None,
13+
item_id: None,
1414
doc: Symbol::intern(s),
1515
kind: DocFragmentKind::SugaredDoc,
1616
indent: 0,

src/librustdoc/clean/utils.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ pub(crate) fn build_deref_target_impls(
195195
if let Some(prim) = target.primitive_type() {
196196
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
197197
for did in prim.impls(tcx).filter(|did| !did.is_local()) {
198-
inline::build_impl(cx, None, did, None, ret);
198+
inline::build_impl(cx, did, None, ret);
199199
}
200200
} else if let Type::Path { path } = target {
201201
let did = path.def_id();
202202
if !did.is_local() {
203-
inline::build_impls(cx, None, did, None, ret);
203+
inline::build_impls(cx, did, None, ret);
204204
}
205205
}
206206
}

0 commit comments

Comments
 (0)