Skip to content

Commit 0574e11

Browse files
committed
if a trait item is shown in search results, hide the impl item
for example, if we're showing `Iterator::next`, we don't need to also show `Range::next` in the results.
1 parent e95db59 commit 0574e11

File tree

5 files changed

+134
-26
lines changed

5 files changed

+134
-26
lines changed

src/librustdoc/formats/cache.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ impl Cache {
148148
Cache { document_private, document_hidden, ..Cache::default() }
149149
}
150150

151+
fn parent_stack_last_impl_and_trait_id(&self) -> (Option<DefId>, Option<DefId>) {
152+
if let Some(ParentStackItem::Impl { item_id, trait_, .. }) = self.parent_stack.last() {
153+
154+
(item_id.as_def_id(), trait_.as_ref().map(|tr| tr.def_id()))
155+
} else {
156+
(None, None)
157+
}
158+
}
159+
151160
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
152161
/// in `krate` due to the data being moved into the `Cache`.
153162
pub(crate) fn populate(cx: &mut DocContext<'_>, mut krate: clean::Crate) -> clean::Crate {
@@ -574,11 +583,8 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
574583
clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
575584
_ => item_def_id,
576585
};
577-
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
578-
item_id.as_def_id()
579-
} else {
580-
None
581-
};
586+
let (impl_id, trait_parent) =
587+
cache.parent_stack_last_impl_and_trait_id();
582588
let search_type = get_function_type_for_search(
583589
item,
584590
tcx,
@@ -596,12 +602,15 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
596602
desc,
597603
parent: parent_did,
598604
parent_idx: None,
605+
trait_parent,
606+
trait_parent_idx: None,
599607
exact_module_path: None,
600608
impl_id,
601609
search_type,
602610
aliases,
603611
deprecation,
604612
};
613+
605614
cache.search_index.push(index_item);
606615
}
607616

@@ -610,19 +619,16 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
610619
/// See [`Cache::orphan_impl_items`].
611620
fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) {
612621
let impl_generics = clean_impl_generics(cache.parent_stack.last());
613-
let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
614-
item_id.as_def_id()
615-
} else {
616-
None
617-
};
622+
let (impl_id, trait_parent) = cache.parent_stack_last_impl_and_trait_id();
618623
let orphan_item =
619-
OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
624+
OrphanImplItem { parent: parent_did, trait_parent, item: item.clone(), impl_generics, impl_id };
620625
cache.orphan_impl_items.push(orphan_item);
621626
}
622627

623628
pub(crate) struct OrphanImplItem {
624629
pub(crate) parent: DefId,
625630
pub(crate) impl_id: Option<DefId>,
631+
pub(crate) trait_parent: Option<DefId>,
626632
pub(crate) item: clean::Item,
627633
pub(crate) impl_generics: Option<(clean::Type, clean::Generics)>,
628634
}

src/librustdoc/html/render/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ pub(crate) struct IndexItem {
134134
pub(crate) desc: String,
135135
pub(crate) parent: Option<DefId>,
136136
pub(crate) parent_idx: Option<usize>,
137+
pub(crate) trait_parent: Option<DefId>,
138+
pub(crate) trait_parent_idx: Option<usize>,
137139
pub(crate) exact_module_path: Option<Vec<Symbol>>,
138140
pub(crate) impl_id: Option<DefId>,
139141
pub(crate) search_type: Option<IndexItemFunctionType>,

src/librustdoc/html/render/search_index.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ impl SerializedSearchIndex {
520520
ty,
521521
module_path,
522522
exact_module_path,
523-
parent,
523+
parent,
524+
trait_parent,
524525
deprecated,
525526
associated_item_disambiguator,
526527
}| EntryData {
@@ -530,6 +531,7 @@ impl SerializedSearchIndex {
530531
exact_module_path: exact_module_path
531532
.and_then(|path_id| map.get(&path_id).copied()),
532533
parent: parent.and_then(|path_id| map.get(&path_id).copied()),
534+
trait_parent: trait_parent.and_then(|path_id| map.get(&path_id).copied()),
533535
deprecated: *deprecated,
534536
associated_item_disambiguator: associated_item_disambiguator.clone(),
535537
},
@@ -788,6 +790,7 @@ struct EntryData {
788790
module_path: Option<usize>,
789791
exact_module_path: Option<usize>,
790792
parent: Option<usize>,
793+
trait_parent: Option<usize>,
791794
deprecated: bool,
792795
associated_item_disambiguator: Option<String>,
793796
}
@@ -803,6 +806,7 @@ impl Serialize for EntryData {
803806
seq.serialize_element(&self.module_path.map(|id| id + 1).unwrap_or(0))?;
804807
seq.serialize_element(&self.exact_module_path.map(|id| id + 1).unwrap_or(0))?;
805808
seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?;
809+
seq.serialize_element(&self.trait_parent.map(|id| id + 1).unwrap_or(0))?;
806810
seq.serialize_element(&if self.deprecated { 1 } else { 0 })?;
807811
if let Some(disambig) = &self.associated_item_disambiguator {
808812
seq.serialize_element(&disambig)?;
@@ -834,6 +838,9 @@ impl<'de> Deserialize<'de> for EntryData {
834838
.ok_or_else(|| A::Error::missing_field("exact_module_path"))?;
835839
let parent: SerializedOptional32 =
836840
v.next_element()?.ok_or_else(|| A::Error::missing_field("parent"))?;
841+
let trait_parent: SerializedOptional32 =
842+
v.next_element()?.ok_or_else(|| A::Error::missing_field("trait_parent"))?;
843+
837844
let deprecated: u32 = v.next_element()?.unwrap_or(0);
838845
let associated_item_disambiguator: Option<String> = v.next_element()?;
839846
Ok(EntryData {
@@ -843,6 +850,7 @@ impl<'de> Deserialize<'de> for EntryData {
843850
exact_module_path: Option::<i32>::from(exact_module_path)
844851
.map(|path| path as usize),
845852
parent: Option::<i32>::from(parent).map(|path| path as usize),
853+
trait_parent: Option::<i32>::from(trait_parent).map(|path| path as usize),
846854
deprecated: deprecated != 0,
847855
associated_item_disambiguator,
848856
})
@@ -1167,7 +1175,7 @@ pub(crate) fn build_index(
11671175

11681176
// Attach all orphan items to the type's definition if the type
11691177
// has since been learned.
1170-
for &OrphanImplItem { impl_id, parent, ref item, ref impl_generics } in &cache.orphan_impl_items
1178+
for &OrphanImplItem { impl_id, parent, trait_parent, ref item, ref impl_generics } in &cache.orphan_impl_items
11711179
{
11721180
if let Some((fqp, _)) = cache.paths.get(&parent) {
11731181
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
@@ -1179,6 +1187,8 @@ pub(crate) fn build_index(
11791187
desc,
11801188
parent: Some(parent),
11811189
parent_idx: None,
1190+
trait_parent,
1191+
trait_parent_idx: None,
11821192
exact_module_path: None,
11831193
impl_id,
11841194
search_type: get_function_type_for_search(
@@ -1275,6 +1285,7 @@ pub(crate) fn build_index(
12751285
module_path: None,
12761286
exact_module_path: None,
12771287
parent: None,
1288+
trait_parent: None,
12781289
deprecated: false,
12791290
associated_item_disambiguator: None,
12801291
}),
@@ -1288,12 +1299,12 @@ pub(crate) fn build_index(
12881299
}
12891300
};
12901301

1291-
// First, populate associated item parents
1302+
// First, populate associated item parents and trait parents
12921303
let crate_items: Vec<&mut IndexItem> = search_index
12931304
.iter_mut()
12941305
.map(|item| {
1295-
item.parent_idx = item.parent.and_then(|defid| {
1296-
cache.paths.get(&defid).map(|&(ref fqp, ty)| {
1306+
let mut defid_to_rowid = |defid, check_external: bool| {
1307+
cache.paths.get(&defid).or_else(|| check_external.then(|| cache.external_paths.get(&defid)).flatten()).map(|&(ref fqp, ty)| {
12971308
let pathid = serialized_index.names.len();
12981309
match serialized_index.crate_paths_index.entry((ty, fqp.clone())) {
12991310
Entry::Occupied(entry) => *entry.get(),
@@ -1319,8 +1330,10 @@ pub(crate) fn build_index(
13191330
usize::try_from(pathid).unwrap()
13201331
}
13211332
}
1322-
})
1323-
});
1333+
})};
1334+
item.parent_idx = item.parent.and_then(|p| defid_to_rowid(p, false));
1335+
item.trait_parent_idx = item.trait_parent.and_then(|p| defid_to_rowid(p, true));
1336+
debug_assert!(!item.trait_parent.is_some() || item.trait_parent_idx.is_some(), "unable to resolve trait parent for {item:?}");
13241337

13251338
if let Some(defid) = item.defid
13261339
&& item.parent_idx.is_none()
@@ -1403,6 +1416,7 @@ pub(crate) fn build_index(
14031416
Some(EntryData {
14041417
ty: item.ty,
14051418
parent: item.parent_idx,
1419+
trait_parent: item.trait_parent_idx,
14061420
module_path,
14071421
exact_module_path,
14081422
deprecated: item.deprecation.is_some(),

src/librustdoc/html/static/js/rustdoc.d.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ declare namespace rustdoc {
241241
modulePath: number?,
242242
exactModulePath: number?,
243243
parent: number?,
244+
traitParent: number?,
244245
deprecated: boolean,
245246
associatedItemDisambiguator: string?,
246247
}
@@ -288,7 +289,8 @@ declare namespace rustdoc {
288289
path: PathData?,
289290
type: FunctionData?,
290291
deprecated: boolean,
291-
parent: { path: PathData, name: string}?,
292+
parent: { path: PathData, name: string }?,
293+
traitParent: { path: PathData, name: string }?,
292294
}
293295

294296
type ItemType = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
@@ -313,7 +315,23 @@ declare namespace rustdoc {
313315
interface ResultObject {
314316
desc: Promise<string|null>,
315317
displayPath: string,
318+
/**
319+
* path to where the item was defined (not inlined),
320+
* then `|`, then the `ItemType` of the item.
321+
*
322+
* This is often a private path, so it should not be displayed,
323+
* but this allows us to use it to reliably deduplicate reexported and inlined items
324+
*/
316325
fullPath: string,
326+
/**
327+
* The `fullPath` of the corrosponding item within a trait.
328+
* For example, for `File::read`, this would be `std::io::Read::read|12`
329+
*
330+
* This is used to hide items from trait impls when the trait itself is in the search results.
331+
*
332+
* `null` if the item is not from a trait impl block.
333+
*/
334+
traitPath: string | null,
317335
href: string,
318336
id: number,
319337
dist: number,

0 commit comments

Comments
 (0)