Skip to content

Commit 0f96d56

Browse files
committed
Restructure add_item_to_search_index to eliminate code paths
Many of the code paths it handled were actually impossible. In other cases, the various checks and transformations were spread around in such a way that it was hard to tell what was going on.
1 parent 7f6b450 commit 0f96d56

File tree

1 file changed

+103
-110
lines changed

1 file changed

+103
-110
lines changed

src/librustdoc/formats/cache.rs

+103-110
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
442442
}
443443

444444
fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
445-
let ((parent_did, parent_path), is_impl_child) = match *item.kind {
445+
// Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
446+
let item_def_id = item.item_id.as_def_id().unwrap();
447+
let (parent_did, parent_path) = match *item.kind {
446448
clean::StrippedItem(..) => return,
447449
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
448450
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
@@ -454,123 +456,114 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
454456
| clean::TyAssocConstItem(..)
455457
| clean::TyAssocTypeItem(..)
456458
| clean::StructFieldItem(..)
457-
| clean::VariantItem(..) => (
458-
(
459-
Some(
460-
cache
461-
.parent_stack
462-
.last()
463-
.expect("parent_stack is empty")
464-
.item_id()
465-
.expect_def_id(),
466-
),
467-
Some(&cache.stack[..cache.stack.len() - 1]),
468-
),
469-
false,
470-
),
459+
| clean::VariantItem(..) => {
460+
// Don't index if containing module is stripped (i.e., private),
461+
// or if item is tuple struct/variant field (name is a number -> not useful for search).
462+
if cache.stripped_mod
463+
|| item.type_() == ItemType::StructField
464+
&& name.as_str().chars().all(|c| c.is_digit(10))
465+
{
466+
return;
467+
}
468+
let parent_did =
469+
cache.parent_stack.last().expect("parent_stack is empty").item_id().expect_def_id();
470+
let parent_path = &cache.stack[..cache.stack.len() - 1];
471+
(Some(parent_did), parent_path)
472+
}
471473
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
472474
let last = cache.parent_stack.last().expect("parent_stack is empty 2");
473-
let did = match &*last {
474-
ParentStackItem::Impl {
475-
// impl Trait for &T { fn method(self); }
476-
//
477-
// When generating a function index with the above shape, we want it
478-
// associated with `T`, not with the primitive reference type. It should
479-
// show up as `T::method`, rather than `reference::method`, in the search
480-
// results page.
481-
for_: clean::Type::BorrowedRef { type_, .. },
482-
..
483-
} => type_.def_id(&cache),
475+
let parent_did = match &*last {
476+
// impl Trait for &T { fn method(self); }
477+
//
478+
// When generating a function index with the above shape, we want it
479+
// associated with `T`, not with the primitive reference type. It should
480+
// show up as `T::method`, rather than `reference::method`, in the search
481+
// results page.
482+
ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => {
483+
type_.def_id(&cache)
484+
}
484485
ParentStackItem::Impl { for_, .. } => for_.def_id(&cache),
485486
ParentStackItem::Type(item_id) => item_id.as_def_id(),
486487
};
487-
let path = did
488-
.and_then(|did| cache.paths.get(&did))
489-
// The current stack not necessarily has correlation
490-
// for where the type was defined. On the other
491-
// hand, `paths` always has the right
492-
// information if present.
493-
.map(|(fqp, _)| &fqp[..fqp.len() - 1]);
494-
((did, path), true)
488+
let Some(parent_did) = parent_did else { return };
489+
// The current stack not necessarily has correlation
490+
// for where the type was defined. On the other
491+
// hand, `paths` always has the right
492+
// information if present.
493+
match cache.paths.get(&parent_did) {
494+
Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]),
495+
None => {
496+
handle_orphan_impl_child(cache, item, parent_did);
497+
return;
498+
}
499+
}
500+
}
501+
_ => {
502+
// Don't index if item is crate root, which is inserted later on when serializing the index.
503+
if item_def_id.is_crate_root() {
504+
return;
505+
}
506+
(None, &*cache.stack)
495507
}
496-
_ => ((None, Some(&*cache.stack)), false),
497508
};
498509

499-
if let Some(parent_did) = parent_did
500-
&& parent_path.is_none()
501-
&& is_impl_child
502-
{
503-
// We have a parent, but we don't know where they're
504-
// defined yet. Wait for later to index this item.
505-
let impl_generics = clean_impl_generics(cache.parent_stack.last());
506-
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last()
507-
{
508-
item_id.as_def_id()
509-
} else {
510-
None
511-
};
512-
let orphan_item =
513-
OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
514-
cache.orphan_impl_items.push(orphan_item);
515-
} else if let Some(path) = parent_path
516-
&& (is_impl_child || !cache.stripped_mod)
517-
{
518-
debug_assert!(!item.is_stripped());
519-
520-
// A crate has a module at its root, containing all items,
521-
// which should not be indexed. The crate-item itself is
522-
// inserted later on when serializing the search-index.
523-
if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root())
524-
&& let ty = item.type_()
525-
&& (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err())
526-
{
527-
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
528-
// For searching purposes, a re-export is a duplicate if:
529-
//
530-
// - It's either an inline, or a true re-export
531-
// - It's got the same name
532-
// - Both of them have the same exact path
533-
let defid = (match &*item.kind {
534-
&clean::ItemKind::ImportItem(ref import) => import.source.did,
535-
_ => None,
536-
})
537-
.or_else(|| item.item_id.as_def_id());
538-
// In case this is a field from a tuple struct, we don't add it into
539-
// the search index because its name is something like "0", which is
540-
// not useful for rustdoc search.
541-
let path = join_with_double_colon(path);
542-
let impl_id =
543-
if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
544-
item_id.as_def_id()
545-
} else {
546-
None
547-
};
548-
let search_type = get_function_type_for_search(
549-
&item,
550-
tcx,
551-
clean_impl_generics(cache.parent_stack.last()).as_ref(),
552-
parent_did,
553-
cache,
554-
);
555-
let aliases = item.attrs.get_doc_aliases();
556-
let deprecation = item.deprecation(tcx);
557-
let index_item = IndexItem {
558-
ty,
559-
defid,
560-
name,
561-
path,
562-
desc,
563-
parent: parent_did,
564-
parent_idx: None,
565-
exact_path: None,
566-
impl_id,
567-
search_type,
568-
aliases,
569-
deprecation,
570-
};
571-
cache.search_index.push(index_item);
572-
}
573-
}
510+
debug_assert!(!item.is_stripped());
511+
512+
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
513+
// For searching purposes, a re-export is a duplicate if:
514+
//
515+
// - It's either an inline, or a true re-export
516+
// - It's got the same name
517+
// - Both of them have the same exact path
518+
let defid = match &*item.kind {
519+
clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
520+
_ => item_def_id,
521+
};
522+
let path = join_with_double_colon(parent_path);
523+
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
524+
item_id.as_def_id()
525+
} else {
526+
None
527+
};
528+
let search_type = get_function_type_for_search(
529+
&item,
530+
tcx,
531+
clean_impl_generics(cache.parent_stack.last()).as_ref(),
532+
parent_did,
533+
cache,
534+
);
535+
let aliases = item.attrs.get_doc_aliases();
536+
let deprecation = item.deprecation(tcx);
537+
let index_item = IndexItem {
538+
ty: item.type_(),
539+
defid: Some(defid),
540+
name,
541+
path,
542+
desc,
543+
parent: parent_did,
544+
parent_idx: None,
545+
exact_path: None,
546+
impl_id,
547+
search_type,
548+
aliases,
549+
deprecation,
550+
};
551+
cache.search_index.push(index_item);
552+
}
553+
554+
/// We have a parent, but we don't know where they're
555+
/// defined yet. Wait for later to index this item.
556+
/// See [`Cache::orphan_impl_items`].
557+
fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) {
558+
let impl_generics = clean_impl_generics(cache.parent_stack.last());
559+
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
560+
item_id.as_def_id()
561+
} else {
562+
None
563+
};
564+
let orphan_item =
565+
OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
566+
cache.orphan_impl_items.push(orphan_item);
574567
}
575568

576569
pub(crate) struct OrphanImplItem {

0 commit comments

Comments
 (0)