cleanup librustdoc by making parent stack store items
This commit is contained in:
parent
767719cc30
commit
718269aab8
2 changed files with 84 additions and 90 deletions
|
@ -94,10 +94,7 @@ pub(crate) struct Cache {
|
||||||
|
|
||||||
// Private fields only used when initially crawling a crate to build a cache
|
// Private fields only used when initially crawling a crate to build a cache
|
||||||
stack: Vec<Symbol>,
|
stack: Vec<Symbol>,
|
||||||
parent_stack: Vec<DefId>,
|
parent_stack: Vec<ParentStackItem>,
|
||||||
impl_generics_stack: Vec<(clean::Type, clean::Generics)>,
|
|
||||||
parent_is_trait_impl: bool,
|
|
||||||
parent_is_blanket_or_auto_impl: bool,
|
|
||||||
stripped_mod: bool,
|
stripped_mod: bool,
|
||||||
|
|
||||||
pub(crate) search_index: Vec<IndexItem>,
|
pub(crate) search_index: Vec<IndexItem>,
|
||||||
|
@ -263,7 +260,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
let (parent, is_inherent_impl_item) = match *item.kind {
|
let (parent, is_inherent_impl_item) = match *item.kind {
|
||||||
clean::StrippedItem(..) => ((None, None), false),
|
clean::StrippedItem(..) => ((None, None), false),
|
||||||
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
|
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
|
||||||
if self.cache.parent_is_trait_impl =>
|
if self
|
||||||
|
.cache
|
||||||
|
.parent_stack
|
||||||
|
.last()
|
||||||
|
.map_or(false, |parent| parent.is_trait_impl()) =>
|
||||||
{
|
{
|
||||||
// skip associated items in trait impls
|
// skip associated items in trait impls
|
||||||
((None, None), false)
|
((None, None), false)
|
||||||
|
@ -274,7 +275,14 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
| clean::StructFieldItem(..)
|
| clean::StructFieldItem(..)
|
||||||
| clean::VariantItem(..) => (
|
| clean::VariantItem(..) => (
|
||||||
(
|
(
|
||||||
Some(*self.cache.parent_stack.last().expect("parent_stack is empty")),
|
Some(
|
||||||
|
self.cache
|
||||||
|
.parent_stack
|
||||||
|
.last()
|
||||||
|
.expect("parent_stack is empty")
|
||||||
|
.item_id()
|
||||||
|
.expect_def_id(),
|
||||||
|
),
|
||||||
Some(&self.cache.stack[..self.cache.stack.len() - 1]),
|
Some(&self.cache.stack[..self.cache.stack.len() - 1]),
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
|
@ -284,8 +292,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
((None, None), false)
|
((None, None), false)
|
||||||
} else {
|
} else {
|
||||||
let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
|
let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
|
||||||
let did = *last;
|
let did = match &*last {
|
||||||
let path = match self.cache.paths.get(&did) {
|
ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache),
|
||||||
|
ParentStackItem::Type(item_id) => item_id.as_def_id(),
|
||||||
|
};
|
||||||
|
let path = match did.and_then(|did| self.cache.paths.get(&did)) {
|
||||||
// The current stack not necessarily has correlation
|
// The current stack not necessarily has correlation
|
||||||
// for where the type was defined. On the other
|
// for where the type was defined. On the other
|
||||||
// hand, `paths` always has the right
|
// hand, `paths` always has the right
|
||||||
|
@ -293,7 +304,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
Some(&(ref fqp, _)) => Some(&fqp[..fqp.len() - 1]),
|
Some(&(ref fqp, _)) => Some(&fqp[..fqp.len() - 1]),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
((Some(*last), path), true)
|
((did, path), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ((None, Some(&*self.cache.stack)), false),
|
_ => ((None, Some(&*self.cache.stack)), false),
|
||||||
|
@ -320,8 +331,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
search_type: get_function_type_for_search(
|
search_type: get_function_type_for_search(
|
||||||
&item,
|
&item,
|
||||||
self.tcx,
|
self.tcx,
|
||||||
self.cache.impl_generics_stack.last(),
|
clean_impl_generics(self.cache.parent_stack.last()).as_ref(),
|
||||||
self.cache.parent_is_blanket_or_auto_impl,
|
|
||||||
self.cache,
|
self.cache,
|
||||||
),
|
),
|
||||||
aliases: item.attrs.get_doc_aliases(),
|
aliases: item.attrs.get_doc_aliases(),
|
||||||
|
@ -331,11 +341,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
(Some(parent), None) if is_inherent_impl_item => {
|
(Some(parent), None) if is_inherent_impl_item => {
|
||||||
// We have a parent, but we don't know where they're
|
// We have a parent, but we don't know where they're
|
||||||
// defined yet. Wait for later to index this item.
|
// defined yet. Wait for later to index this item.
|
||||||
|
let impl_generics = clean_impl_generics(self.cache.parent_stack.last());
|
||||||
self.cache.orphan_impl_items.push(OrphanImplItem {
|
self.cache.orphan_impl_items.push(OrphanImplItem {
|
||||||
parent,
|
parent,
|
||||||
item: item.clone(),
|
item: item.clone(),
|
||||||
impl_generics: self.cache.impl_generics_stack.last().cloned(),
|
impl_generics,
|
||||||
parent_is_blanket_or_auto_impl: self.cache.parent_is_blanket_or_auto_impl,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -411,72 +421,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain the parent stack
|
// Maintain the parent stack.
|
||||||
let orig_parent_is_trait_impl = self.cache.parent_is_trait_impl;
|
let (item, parent_pushed) = match *item.kind {
|
||||||
let parent_pushed = match *item.kind {
|
|
||||||
clean::TraitItem(..)
|
clean::TraitItem(..)
|
||||||
| clean::EnumItem(..)
|
| clean::EnumItem(..)
|
||||||
| clean::ForeignTypeItem
|
| clean::ForeignTypeItem
|
||||||
| clean::StructItem(..)
|
| clean::StructItem(..)
|
||||||
| clean::UnionItem(..)
|
| clean::UnionItem(..)
|
||||||
| clean::VariantItem(..) => {
|
| clean::VariantItem(..)
|
||||||
self.cache.parent_stack.push(item.item_id.expect_def_id());
|
| clean::ImplItem(..) => {
|
||||||
self.cache.parent_is_trait_impl = false;
|
self.cache.parent_stack.push(ParentStackItem::new(&item));
|
||||||
true
|
(self.fold_item_recur(item), true)
|
||||||
}
|
}
|
||||||
clean::ImplItem(ref i) => {
|
_ => (self.fold_item_recur(item), false),
|
||||||
self.cache.parent_is_trait_impl = i.trait_.is_some();
|
|
||||||
match i.for_ {
|
|
||||||
clean::Type::Path { ref path } => {
|
|
||||||
self.cache.parent_stack.push(path.def_id());
|
|
||||||
true
|
|
||||||
}
|
|
||||||
clean::DynTrait(ref bounds, _)
|
|
||||||
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
|
|
||||||
self.cache.parent_stack.push(bounds[0].trait_.def_id());
|
|
||||||
true
|
|
||||||
}
|
|
||||||
ref t => {
|
|
||||||
let prim_did = t
|
|
||||||
.primitive_type()
|
|
||||||
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
|
|
||||||
match prim_did {
|
|
||||||
Some(did) => {
|
|
||||||
self.cache.parent_stack.push(did);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// When recursing into an impl item, make the generics context visible
|
|
||||||
// to the child items.
|
|
||||||
let item = {
|
|
||||||
let mut item = item;
|
|
||||||
let mut old_parent_is_blanket_or_auto_impl = false;
|
|
||||||
if let clean::Item { kind: box clean::ImplItem(ref mut i), .. } = item {
|
|
||||||
old_parent_is_blanket_or_auto_impl = mem::replace(
|
|
||||||
&mut self.cache.parent_is_blanket_or_auto_impl,
|
|
||||||
!matches!(i.kind, clean::ImplKind::Normal),
|
|
||||||
);
|
|
||||||
self.cache.impl_generics_stack.push((
|
|
||||||
mem::replace(&mut i.for_, clean::Type::Infer),
|
|
||||||
mem::replace(
|
|
||||||
&mut i.generics,
|
|
||||||
clean::Generics { params: Vec::new(), where_predicates: Vec::new() },
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let mut item = self.fold_item_recur(item);
|
|
||||||
if let clean::Item { kind: box clean::ImplItem(ref mut i), .. } = item {
|
|
||||||
self.cache.parent_is_blanket_or_auto_impl = old_parent_is_blanket_or_auto_impl;
|
|
||||||
(i.for_, i.generics) = self.cache.impl_generics_stack.pop().expect("pushed above");
|
|
||||||
}
|
|
||||||
item
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Once we've recursively found all the generics, hoard off all the
|
// Once we've recursively found all the generics, hoard off all the
|
||||||
|
@ -549,7 +506,6 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||||
self.cache.parent_stack.pop().expect("parent stack already empty");
|
self.cache.parent_stack.pop().expect("parent stack already empty");
|
||||||
}
|
}
|
||||||
self.cache.stripped_mod = orig_stripped_mod;
|
self.cache.stripped_mod = orig_stripped_mod;
|
||||||
self.cache.parent_is_trait_impl = orig_parent_is_trait_impl;
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,5 +514,56 @@ pub(crate) struct OrphanImplItem {
|
||||||
pub(crate) parent: DefId,
|
pub(crate) parent: DefId,
|
||||||
pub(crate) item: clean::Item,
|
pub(crate) item: clean::Item,
|
||||||
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
|
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
|
||||||
pub(crate) parent_is_blanket_or_auto_impl: bool,
|
}
|
||||||
|
|
||||||
|
/// Information about trait and type parents is tracked while traversing the item tree to build
|
||||||
|
/// the cache.
|
||||||
|
///
|
||||||
|
/// We don't just store `Item` in there, because `Item` contains the list of children being
|
||||||
|
/// traversed and it would be wasteful to clone all that. We also need the item id, so just
|
||||||
|
/// storing `ItemKind` won't work, either.
|
||||||
|
enum ParentStackItem {
|
||||||
|
Impl {
|
||||||
|
for_: clean::Type,
|
||||||
|
trait_: Option<clean::Path>,
|
||||||
|
generics: clean::Generics,
|
||||||
|
kind: clean::ImplKind,
|
||||||
|
item_id: ItemId,
|
||||||
|
},
|
||||||
|
Type(ItemId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParentStackItem {
|
||||||
|
fn new(item: &clean::Item) -> Self {
|
||||||
|
match &*item.kind {
|
||||||
|
clean::ItemKind::ImplItem(clean::Impl { for_, trait_, generics, kind, .. }) => {
|
||||||
|
ParentStackItem::Impl {
|
||||||
|
for_: for_.clone(),
|
||||||
|
trait_: trait_.clone(),
|
||||||
|
generics: generics.clone(),
|
||||||
|
kind: kind.clone(),
|
||||||
|
item_id: item.item_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ParentStackItem::Type(item.item_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn is_trait_impl(&self) -> bool {
|
||||||
|
matches!(self, ParentStackItem::Impl { trait_: Some(..), .. })
|
||||||
|
}
|
||||||
|
fn item_id(&self) -> ItemId {
|
||||||
|
match self {
|
||||||
|
ParentStackItem::Impl { item_id, .. } => *item_id,
|
||||||
|
ParentStackItem::Type(item_id) => *item_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clean_impl_generics(item: Option<&ParentStackItem>) -> Option<(clean::Type, clean::Generics)> {
|
||||||
|
if let Some(ParentStackItem::Impl { for_, generics, kind: clean::ImplKind::Normal, .. }) = item
|
||||||
|
{
|
||||||
|
Some((for_.clone(), generics.clone()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,7 @@ pub(crate) fn build_index<'tcx>(
|
||||||
|
|
||||||
// Attach all orphan items to the type's definition if the type
|
// Attach all orphan items to the type's definition if the type
|
||||||
// has since been learned.
|
// has since been learned.
|
||||||
for &OrphanImplItem { parent, ref item, ref impl_generics, parent_is_blanket_or_auto_impl } in
|
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
|
||||||
&cache.orphan_impl_items
|
|
||||||
{
|
|
||||||
if let Some(&(ref fqp, _)) = cache.paths.get(&parent) {
|
if let Some(&(ref fqp, _)) = cache.paths.get(&parent) {
|
||||||
let desc = item
|
let desc = item
|
||||||
.doc_value()
|
.doc_value()
|
||||||
|
@ -39,13 +37,7 @@ pub(crate) fn build_index<'tcx>(
|
||||||
desc,
|
desc,
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
search_type: get_function_type_for_search(
|
search_type: get_function_type_for_search(item, tcx, impl_generics.as_ref(), cache),
|
||||||
item,
|
|
||||||
tcx,
|
|
||||||
impl_generics.as_ref(),
|
|
||||||
parent_is_blanket_or_auto_impl,
|
|
||||||
cache,
|
|
||||||
),
|
|
||||||
aliases: item.attrs.get_doc_aliases(),
|
aliases: item.attrs.get_doc_aliases(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -201,13 +193,8 @@ pub(crate) fn get_function_type_for_search<'tcx>(
|
||||||
item: &clean::Item,
|
item: &clean::Item,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
impl_generics: Option<&(clean::Type, clean::Generics)>,
|
impl_generics: Option<&(clean::Type, clean::Generics)>,
|
||||||
from_blanket_or_auto_impl: bool,
|
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Option<IndexItemFunctionType> {
|
) -> Option<IndexItemFunctionType> {
|
||||||
if from_blanket_or_auto_impl {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (mut inputs, mut output) = match *item.kind {
|
let (mut inputs, mut output) = match *item.kind {
|
||||||
clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx, impl_generics, cache),
|
clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx, impl_generics, cache),
|
||||||
clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx, impl_generics, cache),
|
clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx, impl_generics, cache),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue