Skip to content

Commit 718269a

Browse files
committed
cleanup librustdoc by making parent stack store items
1 parent 767719c commit 718269a

File tree

2 files changed

+84
-90
lines changed

2 files changed

+84
-90
lines changed

src/librustdoc/formats/cache.rs

+82-75
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,7 @@ pub(crate) struct Cache {
9494

9595
// Private fields only used when initially crawling a crate to build a cache
9696
stack: Vec<Symbol>,
97-
parent_stack: Vec<DefId>,
98-
impl_generics_stack: Vec<(clean::Type, clean::Generics)>,
99-
parent_is_trait_impl: bool,
100-
parent_is_blanket_or_auto_impl: bool,
97+
parent_stack: Vec<ParentStackItem>,
10198
stripped_mod: bool,
10299

103100
pub(crate) search_index: Vec<IndexItem>,
@@ -263,7 +260,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
263260
let (parent, is_inherent_impl_item) = match *item.kind {
264261
clean::StrippedItem(..) => ((None, None), false),
265262
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
266-
if self.cache.parent_is_trait_impl =>
263+
if self
264+
.cache
265+
.parent_stack
266+
.last()
267+
.map_or(false, |parent| parent.is_trait_impl()) =>
267268
{
268269
// skip associated items in trait impls
269270
((None, None), false)
@@ -274,7 +275,14 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
274275
| clean::StructFieldItem(..)
275276
| clean::VariantItem(..) => (
276277
(
277-
Some(*self.cache.parent_stack.last().expect("parent_stack is empty")),
278+
Some(
279+
self.cache
280+
.parent_stack
281+
.last()
282+
.expect("parent_stack is empty")
283+
.item_id()
284+
.expect_def_id(),
285+
),
278286
Some(&self.cache.stack[..self.cache.stack.len() - 1]),
279287
),
280288
false,
@@ -284,16 +292,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
284292
((None, None), false)
285293
} else {
286294
let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
287-
let did = *last;
288-
let path = match self.cache.paths.get(&did) {
295+
let did = match &*last {
296+
ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache),
297+
ParentStackItem::Type(item_id) => item_id.as_def_id(),
298+
};
299+
let path = match did.and_then(|did| self.cache.paths.get(&did)) {
289300
// The current stack not necessarily has correlation
290301
// for where the type was defined. On the other
291302
// hand, `paths` always has the right
292303
// information if present.
293304
Some(&(ref fqp, _)) => Some(&fqp[..fqp.len() - 1]),
294305
None => None,
295306
};
296-
((Some(*last), path), true)
307+
((did, path), true)
297308
}
298309
}
299310
_ => ((None, Some(&*self.cache.stack)), false),
@@ -320,8 +331,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
320331
search_type: get_function_type_for_search(
321332
&item,
322333
self.tcx,
323-
self.cache.impl_generics_stack.last(),
324-
self.cache.parent_is_blanket_or_auto_impl,
334+
clean_impl_generics(self.cache.parent_stack.last()).as_ref(),
325335
self.cache,
326336
),
327337
aliases: item.attrs.get_doc_aliases(),
@@ -331,11 +341,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
331341
(Some(parent), None) if is_inherent_impl_item => {
332342
// We have a parent, but we don't know where they're
333343
// defined yet. Wait for later to index this item.
344+
let impl_generics = clean_impl_generics(self.cache.parent_stack.last());
334345
self.cache.orphan_impl_items.push(OrphanImplItem {
335346
parent,
336347
item: item.clone(),
337-
impl_generics: self.cache.impl_generics_stack.last().cloned(),
338-
parent_is_blanket_or_auto_impl: self.cache.parent_is_blanket_or_auto_impl,
348+
impl_generics,
339349
});
340350
}
341351
_ => {}
@@ -411,72 +421,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
411421
}
412422
}
413423

414-
// Maintain the parent stack
415-
let orig_parent_is_trait_impl = self.cache.parent_is_trait_impl;
416-
let parent_pushed = match *item.kind {
424+
// Maintain the parent stack.
425+
let (item, parent_pushed) = match *item.kind {
417426
clean::TraitItem(..)
418427
| clean::EnumItem(..)
419428
| clean::ForeignTypeItem
420429
| clean::StructItem(..)
421430
| clean::UnionItem(..)
422-
| clean::VariantItem(..) => {
423-
self.cache.parent_stack.push(item.item_id.expect_def_id());
424-
self.cache.parent_is_trait_impl = false;
425-
true
426-
}
427-
clean::ImplItem(ref i) => {
428-
self.cache.parent_is_trait_impl = i.trait_.is_some();
429-
match i.for_ {
430-
clean::Type::Path { ref path } => {
431-
self.cache.parent_stack.push(path.def_id());
432-
true
433-
}
434-
clean::DynTrait(ref bounds, _)
435-
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
436-
self.cache.parent_stack.push(bounds[0].trait_.def_id());
437-
true
438-
}
439-
ref t => {
440-
let prim_did = t
441-
.primitive_type()
442-
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
443-
match prim_did {
444-
Some(did) => {
445-
self.cache.parent_stack.push(did);
446-
true
447-
}
448-
None => false,
449-
}
450-
}
451-
}
452-
}
453-
_ => false,
454-
};
455-
456-
// When recursing into an impl item, make the generics context visible
457-
// to the child items.
458-
let item = {
459-
let mut item = item;
460-
let mut old_parent_is_blanket_or_auto_impl = false;
461-
if let clean::Item { kind: box clean::ImplItem(ref mut i), .. } = item {
462-
old_parent_is_blanket_or_auto_impl = mem::replace(
463-
&mut self.cache.parent_is_blanket_or_auto_impl,
464-
!matches!(i.kind, clean::ImplKind::Normal),
465-
);
466-
self.cache.impl_generics_stack.push((
467-
mem::replace(&mut i.for_, clean::Type::Infer),
468-
mem::replace(
469-
&mut i.generics,
470-
clean::Generics { params: Vec::new(), where_predicates: Vec::new() },
471-
),
472-
));
473-
}
474-
let mut item = self.fold_item_recur(item);
475-
if let clean::Item { kind: box clean::ImplItem(ref mut i), .. } = item {
476-
self.cache.parent_is_blanket_or_auto_impl = old_parent_is_blanket_or_auto_impl;
477-
(i.for_, i.generics) = self.cache.impl_generics_stack.pop().expect("pushed above");
431+
| clean::VariantItem(..)
432+
| clean::ImplItem(..) => {
433+
self.cache.parent_stack.push(ParentStackItem::new(&item));
434+
(self.fold_item_recur(item), true)
478435
}
479-
item
436+
_ => (self.fold_item_recur(item), false),
480437
};
481438

482439
// Once we've recursively found all the generics, hoard off all the
@@ -549,7 +506,6 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
549506
self.cache.parent_stack.pop().expect("parent stack already empty");
550507
}
551508
self.cache.stripped_mod = orig_stripped_mod;
552-
self.cache.parent_is_trait_impl = orig_parent_is_trait_impl;
553509
ret
554510
}
555511
}
@@ -558,5 +514,56 @@ pub(crate) struct OrphanImplItem {
558514
pub(crate) parent: DefId,
559515
pub(crate) item: clean::Item,
560516
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
561-
pub(crate) parent_is_blanket_or_auto_impl: bool,
517+
}
518+
519+
/// Information about trait and type parents is tracked while traversing the item tree to build
520+
/// the cache.
521+
///
522+
/// We don't just store `Item` in there, because `Item` contains the list of children being
523+
/// traversed and it would be wasteful to clone all that. We also need the item id, so just
524+
/// storing `ItemKind` won't work, either.
525+
enum ParentStackItem {
526+
Impl {
527+
for_: clean::Type,
528+
trait_: Option<clean::Path>,
529+
generics: clean::Generics,
530+
kind: clean::ImplKind,
531+
item_id: ItemId,
532+
},
533+
Type(ItemId),
534+
}
535+
536+
impl ParentStackItem {
537+
fn new(item: &clean::Item) -> Self {
538+
match &*item.kind {
539+
clean::ItemKind::ImplItem(clean::Impl { for_, trait_, generics, kind, .. }) => {
540+
ParentStackItem::Impl {
541+
for_: for_.clone(),
542+
trait_: trait_.clone(),
543+
generics: generics.clone(),
544+
kind: kind.clone(),
545+
item_id: item.item_id,
546+
}
547+
}
548+
_ => ParentStackItem::Type(item.item_id),
549+
}
550+
}
551+
fn is_trait_impl(&self) -> bool {
552+
matches!(self, ParentStackItem::Impl { trait_: Some(..), .. })
553+
}
554+
fn item_id(&self) -> ItemId {
555+
match self {
556+
ParentStackItem::Impl { item_id, .. } => *item_id,
557+
ParentStackItem::Type(item_id) => *item_id,
558+
}
559+
}
560+
}
561+
562+
fn clean_impl_generics(item: Option<&ParentStackItem>) -> Option<(clean::Type, clean::Generics)> {
563+
if let Some(ParentStackItem::Impl { for_, generics, kind: clean::ImplKind::Normal, .. }) = item
564+
{
565+
Some((for_.clone(), generics.clone()))
566+
} else {
567+
None
568+
}
562569
}

src/librustdoc/html/render/search_index.rs

+2-15
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ pub(crate) fn build_index<'tcx>(
2525

2626
// Attach all orphan items to the type's definition if the type
2727
// has since been learned.
28-
for &OrphanImplItem { parent, ref item, ref impl_generics, parent_is_blanket_or_auto_impl } in
29-
&cache.orphan_impl_items
30-
{
28+
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
3129
if let Some(&(ref fqp, _)) = cache.paths.get(&parent) {
3230
let desc = item
3331
.doc_value()
@@ -39,13 +37,7 @@ pub(crate) fn build_index<'tcx>(
3937
desc,
4038
parent: Some(parent),
4139
parent_idx: None,
42-
search_type: get_function_type_for_search(
43-
item,
44-
tcx,
45-
impl_generics.as_ref(),
46-
parent_is_blanket_or_auto_impl,
47-
cache,
48-
),
40+
search_type: get_function_type_for_search(item, tcx, impl_generics.as_ref(), cache),
4941
aliases: item.attrs.get_doc_aliases(),
5042
});
5143
}
@@ -201,13 +193,8 @@ pub(crate) fn get_function_type_for_search<'tcx>(
201193
item: &clean::Item,
202194
tcx: TyCtxt<'tcx>,
203195
impl_generics: Option<&(clean::Type, clean::Generics)>,
204-
from_blanket_or_auto_impl: bool,
205196
cache: &Cache,
206197
) -> Option<IndexItemFunctionType> {
207-
if from_blanket_or_auto_impl {
208-
return None;
209-
}
210-
211198
let (mut inputs, mut output) = match *item.kind {
212199
clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx, impl_generics, cache),
213200
clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx, impl_generics, cache),

0 commit comments

Comments
 (0)