Skip to main content

rustdoc/html/render/
search_index.rs

1pub(crate) mod encode;
2mod serde;
3
4use std::collections::BTreeSet;
5use std::collections::hash_map::Entry;
6use std::path::Path;
7use std::string::FromUtf8Error;
8use std::{io, iter};
9
10use ::serde::de::{self, Deserializer, Error as _};
11use ::serde::ser::{SerializeSeq, Serializer};
12use ::serde::{Deserialize, Serialize};
13use rustc_ast::join_path_syms;
14use rustc_attr_ir::find_attr;
15use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
16use rustc_data_structures::thin_vec::ThinVec;
17use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
18use rustc_middle::ty::TyCtxt;
19use rustc_span::def_id::DefId;
20use rustc_span::sym;
21use rustc_span::symbol::{Symbol, kw};
22use stringdex::internals as stringdex_internals;
23use tracing::instrument;
24
25use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate};
26use crate::clean::{self, ExternalLocation, utils};
27use crate::config::ShouldMerge;
28use crate::error::Error;
29use crate::formats::cache::{Cache, OrphanImplItem};
30use crate::formats::item_type::ItemType;
31use crate::html::markdown::short_markdown_summary;
32use crate::html::render::{
33    self, IndexItem, IndexItemFunctionType, IndexItemInfo, RenderType, RenderTypeId,
34};
35
36#[derive(Clone, Debug, Default, Deserialize, Serialize)]
37pub(crate) struct SerializedSearchIndex {
38    // data from disk
39    names: Vec<String>,
40    path_data: Vec<Option<PathData>>,
41    entry_data: Vec<Option<EntryData>>,
42    descs: Vec<String>,
43    function_data: Vec<Option<IndexItemFunctionType>>,
44    alias_pointers: Vec<Option<usize>>,
45    // inverted index for concrete types and generics
46    type_data: Vec<Option<TypeData>>,
47    /// inverted index of generics
48    ///
49    /// - The outermost list has one entry per alpha-normalized generic.
50    ///
51    /// - The second layer is sorted by number of types that appear in the
52    ///   type signature. The search engine iterates over these in order from
53    ///   smallest to largest. Functions with less stuff in their type
54    ///   signature are more likely to be what the user wants, because we never
55    ///   show functions that are *missing* parts of the query, so removing..
56    ///
57    /// - The final layer is the list of functions.
58    generic_inverted_index: Vec<Vec<Vec<u32>>>,
59    // generated in-memory backref cache
60    #[serde(skip)]
61    crate_paths_index: FxHashMap<(ItemType, Vec<Symbol>), usize>,
62}
63
64impl SerializedSearchIndex {
65    fn load(doc_root: &Path, resource_suffix: &str) -> Result<SerializedSearchIndex, Error> {
66        let mut names: Vec<String> = Vec::new();
67        let mut path_data: Vec<Option<PathData>> = Vec::new();
68        let mut entry_data: Vec<Option<EntryData>> = Vec::new();
69        let mut descs: Vec<String> = Vec::new();
70        let mut function_data: Vec<Option<IndexItemFunctionType>> = Vec::new();
71        let mut type_data: Vec<Option<TypeData>> = Vec::new();
72        let mut alias_pointers: Vec<Option<usize>> = Vec::new();
73
74        let mut generic_inverted_index: Vec<Vec<Vec<u32>>> = Vec::new();
75
76        match perform_read_strings(resource_suffix, doc_root, "name", &mut names) {
77            Ok(()) => {
78                perform_read_serde(resource_suffix, doc_root, "path", &mut path_data)?;
79                perform_read_serde(resource_suffix, doc_root, "entry", &mut entry_data)?;
80                perform_read_strings(resource_suffix, doc_root, "desc", &mut descs)?;
81                perform_read_serde(resource_suffix, doc_root, "function", &mut function_data)?;
82                perform_read_serde(resource_suffix, doc_root, "type", &mut type_data)?;
83                perform_read_serde(resource_suffix, doc_root, "alias", &mut alias_pointers)?;
84                perform_read_postings(
85                    resource_suffix,
86                    doc_root,
87                    "generic_inverted_index",
88                    &mut generic_inverted_index,
89                )?;
90            }
91            Err(_) => {
92                names.clear();
93            }
94        }
95        fn perform_read_strings(
96            resource_suffix: &str,
97            doc_root: &Path,
98            column_name: &str,
99            column: &mut Vec<String>,
100        ) -> Result<(), Error> {
101            let root_path = doc_root.join(format!("search.index/root{resource_suffix}.js"));
102            let column_path = doc_root.join(format!("search.index/{column_name}/"));
103
104            let mut consume = |_, cell: &[u8]| {
105                column.push(String::from_utf8(cell.to_vec())?);
106                Ok::<_, FromUtf8Error>(())
107            };
108
109            stringdex_internals::read_data_from_disk_column(
110                root_path,
111                column_name.as_bytes(),
112                column_path.clone(),
113                &mut consume,
114            )
115            .map_err(|error| Error {
116                file: column_path,
117                error: format!("failed to read column from disk: {error}"),
118            })
119        }
120        fn perform_read_serde(
121            resource_suffix: &str,
122            doc_root: &Path,
123            column_name: &str,
124            column: &mut Vec<Option<impl for<'de> Deserialize<'de> + 'static>>,
125        ) -> Result<(), Error> {
126            let root_path = doc_root.join(format!("search.index/root{resource_suffix}.js"));
127            let column_path = doc_root.join(format!("search.index/{column_name}/"));
128
129            let mut consume = |_, cell: &[u8]| {
130                if cell.is_empty() {
131                    column.push(None);
132                } else {
133                    column.push(Some(serde_json::from_slice(cell)?));
134                }
135                Ok::<_, serde_json::Error>(())
136            };
137
138            stringdex_internals::read_data_from_disk_column(
139                root_path,
140                column_name.as_bytes(),
141                column_path.clone(),
142                &mut consume,
143            )
144            .map_err(|error| Error {
145                file: column_path,
146                error: format!("failed to read column from disk: {error}"),
147            })
148        }
149        fn perform_read_postings(
150            resource_suffix: &str,
151            doc_root: &Path,
152            column_name: &str,
153            column: &mut Vec<Vec<Vec<u32>>>,
154        ) -> Result<(), Error> {
155            let root_path = doc_root.join(format!("search.index/root{resource_suffix}.js"));
156            let column_path = doc_root.join(format!("search.index/{column_name}/"));
157
158            fn consumer(
159                column: &mut Vec<Vec<Vec<u32>>>,
160            ) -> impl FnMut(u32, &[u8]) -> io::Result<()> {
161                |_, cell| {
162                    let mut postings = Vec::new();
163                    encode::read_postings_from_string(&mut postings, cell);
164                    column.push(postings);
165                    Ok(())
166                }
167            }
168
169            stringdex_internals::read_data_from_disk_column(
170                root_path,
171                column_name.as_bytes(),
172                column_path.clone(),
173                &mut consumer(column),
174            )
175            .map_err(|error| Error {
176                file: column_path,
177                error: format!("failed to read column from disk: {error}"),
178            })
179        }
180
181        assert_eq!(names.len(), path_data.len());
182        assert_eq!(path_data.len(), entry_data.len());
183        assert_eq!(entry_data.len(), descs.len());
184        assert_eq!(descs.len(), function_data.len());
185        assert_eq!(function_data.len(), type_data.len());
186        assert_eq!(type_data.len(), alias_pointers.len());
187
188        // generic_inverted_index is not the same length as other columns,
189        // because it's actually a completely different set of objects
190
191        let mut crate_paths_index: FxHashMap<(ItemType, Vec<Symbol>), usize> = FxHashMap::default();
192        for (i, (name, path_data)) in names.iter().zip(path_data.iter()).enumerate() {
193            if let Some(path_data) = path_data {
194                let full_path = if path_data.module_path.is_empty() {
195                    vec![Symbol::intern(name)]
196                } else {
197                    let mut full_path = path_data.module_path.to_vec();
198                    full_path.push(Symbol::intern(name));
199                    full_path
200                };
201                crate_paths_index.insert((path_data.ty, full_path), i);
202            }
203        }
204
205        Ok(SerializedSearchIndex {
206            names,
207            path_data,
208            entry_data,
209            descs,
210            function_data,
211            type_data,
212            alias_pointers,
213            generic_inverted_index,
214            crate_paths_index,
215        })
216    }
217    fn push(
218        &mut self,
219        name: String,
220        path_data: Option<PathData>,
221        entry_data: Option<EntryData>,
222        desc: String,
223        function_data: Option<IndexItemFunctionType>,
224        type_data: Option<TypeData>,
225        alias_pointer: Option<usize>,
226    ) -> usize {
227        let index = self.names.len();
228        assert_eq!(self.names.len(), self.path_data.len());
229        if let Some(path_data) = &path_data
230            && let name = Symbol::intern(&name)
231            && let fqp = if path_data.module_path.is_empty() {
232                vec![name]
233            } else {
234                let mut v = path_data.module_path.clone();
235                v.push(name);
236                v
237            }
238            && let Some(&other_path) = self.crate_paths_index.get(&(path_data.ty, fqp))
239            && self.path_data.get(other_path).map_or(false, Option::is_some)
240        {
241            self.path_data.push(None);
242        } else {
243            self.path_data.push(path_data);
244        }
245        self.names.push(name);
246        assert_eq!(self.entry_data.len(), self.descs.len());
247        self.entry_data.push(entry_data);
248        assert_eq!(self.descs.len(), self.function_data.len());
249        self.descs.push(desc);
250        assert_eq!(self.function_data.len(), self.type_data.len());
251        self.function_data.push(function_data);
252        assert_eq!(self.type_data.len(), self.alias_pointers.len());
253        self.type_data.push(type_data);
254        self.alias_pointers.push(alias_pointer);
255        index
256    }
257    /// Add potential search result to the database and return the row ID.
258    ///
259    /// The returned ID can be used to attach more data to the search result.
260    fn add_entry(&mut self, name: Symbol, entry_data: EntryData, desc: String) -> usize {
261        let fqp = if let Some(module_path_index) = entry_data.module_path {
262            self.path_data[module_path_index]
263                .as_ref()
264                .unwrap()
265                .module_path
266                .iter()
267                .copied()
268                .chain([Symbol::intern(&self.names[module_path_index]), name])
269                .collect()
270        } else {
271            vec![name]
272        };
273        // If a path with the same name already exists, but no entry does,
274        // we can fill in the entry without having to allocate a new row ID.
275        //
276        // Because paths and entries both share the same index, using the same
277        // ID saves space by making the tree smaller.
278        if let Some(&other_path) = self.crate_paths_index.get(&(entry_data.ty, fqp))
279            && self.entry_data[other_path].is_none()
280            && self.descs[other_path].is_empty()
281        {
282            self.entry_data[other_path] = Some(entry_data);
283            self.descs[other_path] = desc;
284            other_path
285        } else {
286            self.push(name.as_str().to_string(), None, Some(entry_data), desc, None, None, None)
287        }
288    }
289    fn push_path(&mut self, name: String, path_data: PathData) -> usize {
290        self.push(name, Some(path_data), None, String::new(), None, None, None)
291    }
292    fn push_type(&mut self, name: String, path_data: PathData, type_data: TypeData) -> usize {
293        self.push(name, Some(path_data), None, String::new(), None, Some(type_data), None)
294    }
295    fn push_alias(&mut self, name: String, alias_pointer: usize) -> usize {
296        self.push(name, None, None, String::new(), None, None, Some(alias_pointer))
297    }
298
299    fn get_id_by_module_path(&mut self, path: &[Symbol]) -> usize {
300        let ty = if path.len() == 1 { ItemType::ExternCrate } else { ItemType::Module };
301        match self.crate_paths_index.entry((ty, path.to_vec())) {
302            Entry::Occupied(index) => *index.get(),
303            Entry::Vacant(slot) => {
304                slot.insert(self.path_data.len());
305                let (name, module_path) = path.split_last().unwrap();
306                self.push_path(
307                    name.as_str().to_string(),
308                    PathData { ty, module_path: module_path.to_vec(), exact_module_path: None },
309                )
310            }
311        }
312    }
313
314    pub(crate) fn union(mut self, other: &SerializedSearchIndex) -> SerializedSearchIndex {
315        let other_entryid_offset = self.names.len();
316        let mut map_other_pathid_to_self_pathid = Vec::new();
317        let mut skips = FxHashSet::default();
318
319        fn remap_entry_data(
320            other_entry_data: &EntryData,
321            map_other_pathid_to_self_pathid: &[usize],
322        ) -> EntryData {
323            EntryData {
324                parent: other_entry_data
325                    .parent
326                    .map(|parent| map_other_pathid_to_self_pathid[parent])
327                    .clone(),
328                module_path: other_entry_data
329                    .module_path
330                    .map(|path| map_other_pathid_to_self_pathid[path])
331                    .clone(),
332                exact_module_path: other_entry_data
333                    .exact_module_path
334                    .map(|exact_path| map_other_pathid_to_self_pathid[exact_path])
335                    .clone(),
336                krate: map_other_pathid_to_self_pathid[other_entry_data.krate],
337                ..other_entry_data.clone()
338            }
339        }
340
341        for (other_pathid, other_path_data) in other.path_data.iter().enumerate() {
342            if let Some(other_path_data) = other_path_data {
343                let name = Symbol::intern(&other.names[other_pathid]);
344                let fqp =
345                    other_path_data.module_path.iter().copied().chain(iter::once(name)).collect();
346                let self_pathid = other_entryid_offset + other_pathid;
347                let self_pathid = match self.crate_paths_index.entry((other_path_data.ty, fqp)) {
348                    Entry::Vacant(slot) => {
349                        slot.insert(self_pathid);
350                        self_pathid
351                    }
352                    Entry::Occupied(existing_entryid) => {
353                        skips.insert(other_pathid);
354                        let self_pathid = *existing_entryid.get();
355                        let new_type_data = match (
356                            self.type_data[self_pathid].take(),
357                            other.type_data[other_pathid].as_ref(),
358                        ) {
359                            (Some(self_type_data), None) => Some(self_type_data),
360                            (None, Some(other_type_data)) => Some(TypeData {
361                                search_unbox: other_type_data.search_unbox,
362                                inverted_function_inputs_index: other_type_data
363                                    .inverted_function_inputs_index
364                                    .iter()
365                                    .cloned()
366                                    .map(|mut list: Vec<u32>| {
367                                        for fnid in &mut list {
368                                            assert!(
369                                                other.function_data
370                                                    [usize::try_from(*fnid).unwrap()]
371                                                .is_some(),
372                                            );
373                                            // this is valid because we call `self.push()` once, exactly, for every entry,
374                                            // even if we're just pushing a tombstone
375                                            *fnid += u32::try_from(other_entryid_offset).unwrap();
376                                        }
377                                        list
378                                    })
379                                    .collect(),
380                                inverted_function_output_index: other_type_data
381                                    .inverted_function_output_index
382                                    .iter()
383                                    .cloned()
384                                    .map(|mut list: Vec<u32>| {
385                                        for fnid in &mut list {
386                                            assert!(
387                                                other.function_data
388                                                    [usize::try_from(*fnid).unwrap()]
389                                                .is_some(),
390                                            );
391                                            // this is valid because we call `self.push()` once, exactly, for every entry,
392                                            // even if we're just pushing a tombstone
393                                            *fnid += u32::try_from(other_entryid_offset).unwrap();
394                                        }
395                                        list
396                                    })
397                                    .collect(),
398                            }),
399                            (Some(mut self_type_data), Some(other_type_data)) => {
400                                for (size, other_list) in other_type_data
401                                    .inverted_function_inputs_index
402                                    .iter()
403                                    .enumerate()
404                                {
405                                    while self_type_data.inverted_function_inputs_index.len()
406                                        <= size
407                                    {
408                                        self_type_data
409                                            .inverted_function_inputs_index
410                                            .push(Vec::new());
411                                    }
412                                    self_type_data.inverted_function_inputs_index[size].extend(
413                                        other_list.iter().copied().map(|fnid| {
414                                            assert!(
415                                                other.function_data[usize::try_from(fnid).unwrap()]
416                                                    .is_some(),
417                                            );
418                                            // this is valid because we call `self.push()` once, exactly, for every entry,
419                                            // even if we're just pushing a tombstone
420                                            fnid + u32::try_from(other_entryid_offset).unwrap()
421                                        }),
422                                    )
423                                }
424                                for (size, other_list) in other_type_data
425                                    .inverted_function_output_index
426                                    .iter()
427                                    .enumerate()
428                                {
429                                    while self_type_data.inverted_function_output_index.len()
430                                        <= size
431                                    {
432                                        self_type_data
433                                            .inverted_function_output_index
434                                            .push(Vec::new());
435                                    }
436                                    self_type_data.inverted_function_output_index[size].extend(
437                                        other_list.iter().copied().map(|fnid| {
438                                            assert!(
439                                                other.function_data[usize::try_from(fnid).unwrap()]
440                                                    .is_some(),
441                                            );
442                                            // this is valid because we call `self.push()` once, exactly, for every entry,
443                                            // even if we're just pushing a tombstone
444                                            fnid + u32::try_from(other_entryid_offset).unwrap()
445                                        }),
446                                    )
447                                }
448                                Some(self_type_data)
449                            }
450                            (None, None) => None,
451                        };
452                        self.type_data[self_pathid] = new_type_data;
453                        self_pathid
454                    }
455                };
456                map_other_pathid_to_self_pathid.push(self_pathid);
457            } else {
458                // if this gets used, we want it to crash
459                // this should be impossible as a valid index, since some of the
460                // memory must be used for stuff other than the list
461                map_other_pathid_to_self_pathid.push(!0);
462            }
463        }
464        for other_entryid in 0..other.names.len() {
465            self.push(
466                other.names[other_entryid].clone(),
467                if skips.contains(&other_entryid) {
468                    None
469                } else {
470                    other.path_data[other_entryid].clone()
471                },
472                other.entry_data[other_entryid].as_ref().map(|other_entry_data| {
473                    remap_entry_data(other_entry_data, &map_other_pathid_to_self_pathid)
474                }),
475                other.descs[other_entryid].clone(),
476                other.function_data[other_entryid].clone().map(|mut func| {
477                    fn map_fn_sig_item(
478                        map_other_pathid_to_self_pathid: &Vec<usize>,
479                        ty: &mut RenderType,
480                    ) {
481                        match ty.id {
482                            None => {}
483                            Some(RenderTypeId::Index(generic)) if generic < 0 => {}
484                            Some(RenderTypeId::Index(id)) => {
485                                let id = usize::try_from(id).unwrap();
486                                let id = map_other_pathid_to_self_pathid[id];
487                                assert!(id != !0);
488                                ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
489                            }
490                            _ => unreachable!(),
491                        }
492                        if let Some(generics) = &mut ty.generics {
493                            for generic in generics {
494                                map_fn_sig_item(map_other_pathid_to_self_pathid, generic);
495                            }
496                        }
497                        if let Some(bindings) = &mut ty.bindings {
498                            for (param, constraints) in bindings {
499                                *param = match *param {
500                                    param @ RenderTypeId::Index(generic) if generic < 0 => param,
501                                    RenderTypeId::Index(id) => {
502                                        let id = usize::try_from(id).unwrap();
503                                        let id = map_other_pathid_to_self_pathid[id];
504                                        assert!(id != !0);
505                                        RenderTypeId::Index(isize::try_from(id).unwrap())
506                                    }
507                                    _ => unreachable!(),
508                                };
509                                for constraint in constraints {
510                                    map_fn_sig_item(map_other_pathid_to_self_pathid, constraint);
511                                }
512                            }
513                        }
514                    }
515                    for input in &mut func.inputs {
516                        map_fn_sig_item(&map_other_pathid_to_self_pathid, input);
517                    }
518                    for output in &mut func.output {
519                        map_fn_sig_item(&map_other_pathid_to_self_pathid, output);
520                    }
521                    for clause in &mut func.where_clause {
522                        for entry in clause {
523                            map_fn_sig_item(&map_other_pathid_to_self_pathid, entry);
524                        }
525                    }
526                    func
527                }),
528                if skips.contains(&other_entryid) {
529                    None
530                } else {
531                    other.type_data[other_entryid].as_ref().map(|type_data| TypeData {
532                        inverted_function_inputs_index: type_data
533                            .inverted_function_inputs_index
534                            .iter()
535                            .cloned()
536                            .map(|mut list| {
537                                for fnid in &mut list {
538                                    assert!(
539                                        other.function_data[usize::try_from(*fnid).unwrap()]
540                                            .is_some(),
541                                    );
542                                    // this is valid because we call `self.push()` once, exactly, for every entry,
543                                    // even if we're just pushing a tombstone
544                                    *fnid += u32::try_from(other_entryid_offset).unwrap();
545                                }
546                                list
547                            })
548                            .collect(),
549                        inverted_function_output_index: type_data
550                            .inverted_function_output_index
551                            .iter()
552                            .cloned()
553                            .map(|mut list| {
554                                for fnid in &mut list {
555                                    assert!(
556                                        other.function_data[usize::try_from(*fnid).unwrap()]
557                                            .is_some(),
558                                    );
559                                    // this is valid because we call `self.push()` once, exactly, for every entry,
560                                    // even if we're just pushing a tombstone
561                                    *fnid += u32::try_from(other_entryid_offset).unwrap();
562                                }
563                                list
564                            })
565                            .collect(),
566                        search_unbox: type_data.search_unbox,
567                    })
568                },
569                other.alias_pointers[other_entryid]
570                    .map(|alias_pointer| alias_pointer + other_entryid_offset),
571            );
572        }
573        if other.generic_inverted_index.len() > self.generic_inverted_index.len() {
574            self.generic_inverted_index.resize(other.generic_inverted_index.len(), Vec::new());
575        }
576        for (other_generic_inverted_index, self_generic_inverted_index) in
577            iter::zip(&other.generic_inverted_index, &mut self.generic_inverted_index)
578        {
579            if other_generic_inverted_index.len() > self_generic_inverted_index.len() {
580                self_generic_inverted_index.resize(other_generic_inverted_index.len(), Vec::new());
581            }
582            for (other_list, self_list) in
583                iter::zip(other_generic_inverted_index, self_generic_inverted_index)
584            {
585                self_list.extend(
586                    other_list
587                        .iter()
588                        .copied()
589                        .map(|fnid| fnid + u32::try_from(other_entryid_offset).unwrap()),
590                );
591            }
592        }
593        self
594    }
595
596    pub(crate) fn sort(self) -> SerializedSearchIndex {
597        let mut idlist: Vec<usize> = (0..self.names.len()).collect();
598        // nameless entries are tombstones, and will be removed after sorting
599        // sort shorter names first, so that we can present them in order out of search.js
600        idlist.sort_by_key(|&id| {
601            (
602                self.names[id].is_empty(),
603                self.names[id].len(),
604                &self.names[id],
605                self.entry_data[id].as_ref().map_or("", |entry| self.names[entry.krate].as_str()),
606                self.path_data[id].as_ref().map_or(&[][..], |entry| &entry.module_path[..]),
607            )
608        });
609        let map = FxHashMap::from_iter(
610            idlist.iter().enumerate().map(|(new_id, &old_id)| (old_id, new_id)),
611        );
612        let mut new = SerializedSearchIndex::default();
613        for &id in &idlist {
614            if self.names[id].is_empty() {
615                break;
616            }
617            new.push(
618                self.names[id].clone(),
619                self.path_data[id].clone(),
620                self.entry_data[id].as_ref().map(
621                    |EntryData {
622                         krate,
623                         ty,
624                         module_path,
625                         exact_module_path,
626                         parent,
627                         trait_parent,
628                         deprecated,
629                         unstable,
630                         associated_item_disambiguator_or_extern_crate_url:
631                             associated_item_disambiguator,
632                     }| EntryData {
633                        krate: *map.get(krate).unwrap(),
634                        ty: *ty,
635                        module_path: module_path.and_then(|path_id| map.get(&path_id).copied()),
636                        exact_module_path: exact_module_path
637                            .and_then(|path_id| map.get(&path_id).copied()),
638                        parent: parent.and_then(|path_id| map.get(&path_id).copied()),
639                        trait_parent: trait_parent.and_then(|path_id| map.get(&path_id).copied()),
640                        deprecated: *deprecated,
641                        unstable: *unstable,
642                        associated_item_disambiguator_or_extern_crate_url:
643                            associated_item_disambiguator.clone(),
644                    },
645                ),
646                self.descs[id].clone(),
647                self.function_data[id].clone().map(|mut func| {
648                    fn map_fn_sig_item(map: &FxHashMap<usize, usize>, ty: &mut RenderType) {
649                        match ty.id {
650                            None => {}
651                            Some(RenderTypeId::Index(generic)) if generic < 0 => {}
652                            Some(RenderTypeId::Index(id)) => {
653                                let id = usize::try_from(id).unwrap();
654                                let id = *map.get(&id).unwrap();
655                                assert!(id != !0);
656                                ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
657                            }
658                            _ => unreachable!(),
659                        }
660                        if let Some(generics) = &mut ty.generics {
661                            for generic in generics {
662                                map_fn_sig_item(map, generic);
663                            }
664                        }
665                        if let Some(bindings) = &mut ty.bindings {
666                            for (param, constraints) in bindings {
667                                *param = match *param {
668                                    param @ RenderTypeId::Index(generic) if generic < 0 => param,
669                                    RenderTypeId::Index(id) => {
670                                        let id = usize::try_from(id).unwrap();
671                                        let id = *map.get(&id).unwrap();
672                                        assert!(id != !0);
673                                        RenderTypeId::Index(isize::try_from(id).unwrap())
674                                    }
675                                    _ => unreachable!(),
676                                };
677                                for constraint in constraints {
678                                    map_fn_sig_item(map, constraint);
679                                }
680                            }
681                        }
682                    }
683                    for input in &mut func.inputs {
684                        map_fn_sig_item(&map, input);
685                    }
686                    for output in &mut func.output {
687                        map_fn_sig_item(&map, output);
688                    }
689                    for clause in &mut func.where_clause {
690                        for entry in clause {
691                            map_fn_sig_item(&map, entry);
692                        }
693                    }
694                    func
695                }),
696                self.type_data[id].as_ref().map(
697                    |TypeData {
698                         search_unbox,
699                         inverted_function_inputs_index,
700                         inverted_function_output_index,
701                     }| {
702                        let inverted_function_inputs_index: Vec<Vec<u32>> =
703                            inverted_function_inputs_index
704                                .iter()
705                                .cloned()
706                                .map(|mut list| {
707                                    for id in &mut list {
708                                        *id = u32::try_from(
709                                            *map.get(&usize::try_from(*id).unwrap()).unwrap(),
710                                        )
711                                        .unwrap();
712                                    }
713                                    list.sort();
714                                    list
715                                })
716                                .collect();
717                        let inverted_function_output_index: Vec<Vec<u32>> =
718                            inverted_function_output_index
719                                .iter()
720                                .cloned()
721                                .map(|mut list| {
722                                    for id in &mut list {
723                                        *id = u32::try_from(
724                                            *map.get(&usize::try_from(*id).unwrap()).unwrap(),
725                                        )
726                                        .unwrap();
727                                    }
728                                    list.sort();
729                                    list
730                                })
731                                .collect();
732                        TypeData {
733                            search_unbox: *search_unbox,
734                            inverted_function_inputs_index,
735                            inverted_function_output_index,
736                        }
737                    },
738                ),
739                self.alias_pointers[id].and_then(|alias| {
740                    if self.names[alias].is_empty() { None } else { map.get(&alias).copied() }
741                }),
742            );
743        }
744        new.generic_inverted_index = self
745            .generic_inverted_index
746            .into_iter()
747            .map(|mut postings| {
748                for list in postings.iter_mut() {
749                    let mut new_list: Vec<u32> = list
750                        .iter()
751                        .copied()
752                        .filter_map(|id| u32::try_from(*map.get(&usize::try_from(id).ok()?)?).ok())
753                        .collect();
754                    new_list.sort();
755                    *list = new_list;
756                }
757                postings
758            })
759            .collect();
760        new
761    }
762
763    pub(crate) fn write_to(self, doc_root: &Path, resource_suffix: &str) -> Result<(), Error> {
764        let SerializedSearchIndex {
765            names,
766            path_data,
767            entry_data,
768            descs,
769            function_data,
770            type_data,
771            alias_pointers,
772            generic_inverted_index,
773            crate_paths_index: _,
774        } = self;
775        let mut serialized_root = Vec::new();
776        serialized_root.extend_from_slice(br#"rr_('{"normalizedName":{"I":""#);
777        let normalized_names = names
778            .iter()
779            .map(|name| {
780                if name.contains("_") {
781                    name.replace("_", "").to_ascii_lowercase()
782                } else {
783                    name.to_ascii_lowercase()
784                }
785            })
786            .collect::<Vec<String>>();
787        let names_search_tree = stringdex_internals::tree::encode_search_tree_ukkonen(
788            normalized_names.iter().map(|name| name.as_bytes()),
789        );
790        let dir_path = doc_root.join(format!("search.index/"));
791        let _ = std::fs::remove_dir_all(&dir_path); // if already missing, no problem
792        stringdex_internals::write_tree_to_disk(
793            &names_search_tree,
794            &dir_path,
795            &mut serialized_root,
796        )
797        .map_err(|error| Error {
798            file: dir_path,
799            error: format!("failed to write name tree to disk: {error}"),
800        })?;
801        std::mem::drop(names_search_tree);
802        serialized_root.extend_from_slice(br#"","#);
803        serialized_root.extend_from_slice(&perform_write_strings(
804            doc_root,
805            "normalizedName",
806            normalized_names.into_iter(),
807        )?);
808        serialized_root.extend_from_slice(br#"},"crateNames":{"#);
809        let mut crates: Vec<&[u8]> = entry_data
810            .iter()
811            .filter_map(|entry_data| Some(names[entry_data.as_ref()?.krate].as_bytes()))
812            .collect();
813        crates.sort();
814        crates.dedup();
815        serialized_root.extend_from_slice(&perform_write_strings(
816            doc_root,
817            "crateNames",
818            crates.into_iter(),
819        )?);
820        serialized_root.extend_from_slice(br#"},"name":{"#);
821        serialized_root.extend_from_slice(&perform_write_strings(doc_root, "name", names.iter())?);
822        serialized_root.extend_from_slice(br#"},"path":{"#);
823        serialized_root.extend_from_slice(&perform_write_serde(doc_root, "path", path_data)?);
824        serialized_root.extend_from_slice(br#"},"entry":{"#);
825        serialized_root.extend_from_slice(&perform_write_serde(doc_root, "entry", entry_data)?);
826        serialized_root.extend_from_slice(br#"},"desc":{"#);
827        serialized_root.extend_from_slice(&perform_write_strings(
828            doc_root,
829            "desc",
830            descs.into_iter(),
831        )?);
832        serialized_root.extend_from_slice(br#"},"function":{"#);
833        serialized_root.extend_from_slice(&perform_write_serde(
834            doc_root,
835            "function",
836            function_data,
837        )?);
838        serialized_root.extend_from_slice(br#"},"type":{"#);
839        serialized_root.extend_from_slice(&perform_write_serde(doc_root, "type", type_data)?);
840        serialized_root.extend_from_slice(br#"},"alias":{"#);
841        serialized_root.extend_from_slice(&perform_write_serde(doc_root, "alias", alias_pointers)?);
842        serialized_root.extend_from_slice(br#"},"generic_inverted_index":{"#);
843        serialized_root.extend_from_slice(&perform_write_postings(
844            doc_root,
845            "generic_inverted_index",
846            generic_inverted_index,
847        )?);
848        serialized_root.extend_from_slice(br#"}}')"#);
849        fn perform_write_strings(
850            doc_root: &Path,
851            dirname: &str,
852            mut column: impl Iterator<Item = impl AsRef<[u8]> + Clone> + ExactSizeIterator,
853        ) -> Result<Vec<u8>, Error> {
854            let dir_path = doc_root.join(format!("search.index/{dirname}"));
855            stringdex_internals::write_data_to_disk(&mut column, &dir_path).map_err(|error| Error {
856                file: dir_path,
857                error: format!("failed to write column to disk: {error}"),
858            })
859        }
860        fn perform_write_serde(
861            doc_root: &Path,
862            dirname: &str,
863            column: Vec<Option<impl Serialize>>,
864        ) -> Result<Vec<u8>, Error> {
865            perform_write_strings(
866                doc_root,
867                dirname,
868                column.into_iter().map(|value| {
869                    if let Some(value) = value {
870                        serde_json::to_vec(&value).unwrap()
871                    } else {
872                        Vec::new()
873                    }
874                }),
875            )
876        }
877        fn perform_write_postings(
878            doc_root: &Path,
879            dirname: &str,
880            column: Vec<Vec<Vec<u32>>>,
881        ) -> Result<Vec<u8>, Error> {
882            perform_write_strings(
883                doc_root,
884                dirname,
885                column.into_iter().map(|postings| {
886                    let mut buf = Vec::new();
887                    encode::write_postings_to_string(&postings, &mut buf);
888                    buf
889                }),
890            )
891        }
892        std::fs::write(
893            doc_root.join(format!("search.index/root{resource_suffix}.js")),
894            serialized_root,
895        )
896        .map_err(|error| Error {
897            file: doc_root.join(format!("search.index/root{resource_suffix}.js")),
898            error: format!("failed to write root to disk: {error}"),
899        })?;
900        Ok(())
901    }
902}
903
904#[derive(Clone, Debug)]
905struct EntryData {
906    krate: usize,
907    ty: ItemType,
908    module_path: Option<usize>,
909    exact_module_path: Option<usize>,
910    parent: Option<usize>,
911    trait_parent: Option<usize>,
912    deprecated: bool,
913    unstable: bool,
914    associated_item_disambiguator_or_extern_crate_url: Option<String>,
915}
916
917impl Serialize for EntryData {
918    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
919    where
920        S: Serializer,
921    {
922        let mut seq = serializer.serialize_seq(None)?;
923        seq.serialize_element(&self.krate)?;
924        seq.serialize_element(&self.ty)?;
925        seq.serialize_element(&self.module_path.map(|id| id + 1).unwrap_or(0))?;
926        seq.serialize_element(&self.exact_module_path.map(|id| id + 1).unwrap_or(0))?;
927        seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?;
928        seq.serialize_element(&self.trait_parent.map(|id| id + 1).unwrap_or(0))?;
929        seq.serialize_element(&if self.deprecated { 1 } else { 0 })?;
930        seq.serialize_element(&if self.unstable { 1 } else { 0 })?;
931        if let Some(disambig) = &self.associated_item_disambiguator_or_extern_crate_url {
932            seq.serialize_element(&disambig)?;
933        }
934        seq.end()
935    }
936}
937
938impl<'de> Deserialize<'de> for EntryData {
939    fn deserialize<D>(deserializer: D) -> Result<EntryData, D::Error>
940    where
941        D: Deserializer<'de>,
942    {
943        struct EntryDataVisitor;
944        impl<'de> de::Visitor<'de> for EntryDataVisitor {
945            type Value = EntryData;
946            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
947                write!(formatter, "path data")
948            }
949            fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<EntryData, A::Error> {
950                let krate: usize =
951                    v.next_element()?.ok_or_else(|| A::Error::missing_field("krate"))?;
952                let ty: ItemType =
953                    v.next_element()?.ok_or_else(|| A::Error::missing_field("ty"))?;
954                let module_path: SerializedOptional32 =
955                    v.next_element()?.ok_or_else(|| A::Error::missing_field("module_path"))?;
956                let exact_module_path: SerializedOptional32 = v
957                    .next_element()?
958                    .ok_or_else(|| A::Error::missing_field("exact_module_path"))?;
959                let parent: SerializedOptional32 =
960                    v.next_element()?.ok_or_else(|| A::Error::missing_field("parent"))?;
961                let trait_parent: SerializedOptional32 =
962                    v.next_element()?.ok_or_else(|| A::Error::missing_field("trait_parent"))?;
963
964                let deprecated: u32 = v.next_element()?.unwrap_or(0);
965                let unstable: u32 = v.next_element()?.unwrap_or(0);
966                let associated_item_disambiguator: Option<String> = v.next_element()?;
967                Ok(EntryData {
968                    krate,
969                    ty,
970                    module_path: Option::<i32>::from(module_path).map(|path| path as usize),
971                    exact_module_path: Option::<i32>::from(exact_module_path)
972                        .map(|path| path as usize),
973                    parent: Option::<i32>::from(parent).map(|path| path as usize),
974                    trait_parent: Option::<i32>::from(trait_parent).map(|path| path as usize),
975                    deprecated: deprecated != 0,
976                    unstable: unstable != 0,
977                    associated_item_disambiguator_or_extern_crate_url:
978                        associated_item_disambiguator,
979                })
980            }
981        }
982        deserializer.deserialize_any(EntryDataVisitor)
983    }
984}
985
986#[derive(Clone, Debug)]
987struct PathData {
988    ty: ItemType,
989    module_path: Vec<Symbol>,
990    exact_module_path: Option<Vec<Symbol>>,
991}
992
993impl Serialize for PathData {
994    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
995    where
996        S: Serializer,
997    {
998        let mut seq = serializer.serialize_seq(None)?;
999        seq.serialize_element(&self.ty)?;
1000        seq.serialize_element(&if self.module_path.is_empty() {
1001            String::new()
1002        } else {
1003            join_path_syms(&self.module_path)
1004        })?;
1005        if let Some(ref path) = self.exact_module_path {
1006            seq.serialize_element(&if path.is_empty() {
1007                String::new()
1008            } else {
1009                join_path_syms(path)
1010            })?;
1011        }
1012        seq.end()
1013    }
1014}
1015
1016impl<'de> Deserialize<'de> for PathData {
1017    fn deserialize<D>(deserializer: D) -> Result<PathData, D::Error>
1018    where
1019        D: Deserializer<'de>,
1020    {
1021        struct PathDataVisitor;
1022        impl<'de> de::Visitor<'de> for PathDataVisitor {
1023            type Value = PathData;
1024            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1025                write!(formatter, "path data")
1026            }
1027            fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<PathData, A::Error> {
1028                let ty: ItemType =
1029                    v.next_element()?.ok_or_else(|| A::Error::missing_field("ty"))?;
1030                let module_path: String =
1031                    v.next_element()?.ok_or_else(|| A::Error::missing_field("module_path"))?;
1032                let exact_module_path: Option<String> =
1033                    v.next_element()?.and_then(SerializedOptionalString::into);
1034                Ok(PathData {
1035                    ty,
1036                    module_path: if module_path.is_empty() {
1037                        vec![]
1038                    } else {
1039                        module_path.split("::").map(Symbol::intern).collect()
1040                    },
1041                    exact_module_path: exact_module_path.map(|path| {
1042                        if path.is_empty() {
1043                            vec![]
1044                        } else {
1045                            path.split("::").map(Symbol::intern).collect()
1046                        }
1047                    }),
1048                })
1049            }
1050        }
1051        deserializer.deserialize_any(PathDataVisitor)
1052    }
1053}
1054
1055#[derive(Clone, Debug)]
1056struct TypeData {
1057    /// If set to "true", the generics can be matched without having to
1058    /// mention the type itself. The truth table, assuming `Unboxable`
1059    /// has `search_unbox = true` and `Inner` has `search_unbox = false`
1060    ///
1061    /// | **query**          | `Unboxable<Inner>` | `Inner` | `Inner<Unboxable>` |
1062    /// |--------------------|--------------------|---------|--------------------|
1063    /// | `Inner`            | yes                | yes     | yes                |
1064    /// | `Unboxable`        | yes                | no      | no                 |
1065    /// | `Unboxable<Inner>` | yes                | no      | no                 |
1066    /// | `Inner<Unboxable>` | no                 | no      | yes                |
1067    search_unbox: bool,
1068    /// List of functions that mention this type in their type signature,
1069    /// on the left side of the `->` arrow.
1070    ///
1071    /// - The outer layer is sorted by number of types that appear in the
1072    ///   type signature. The search engine iterates over these in order from
1073    ///   smallest to largest. Functions with less stuff in their type
1074    ///   signature are more likely to be what the user wants, because we never
1075    ///   show functions that are *missing* parts of the query, so removing..
1076    ///
1077    /// - The inner layer is the list of functions.
1078    inverted_function_inputs_index: Vec<Vec<u32>>,
1079    /// List of functions that mention this type in their type signature,
1080    /// on the right side of the `->` arrow.
1081    inverted_function_output_index: Vec<Vec<u32>>,
1082}
1083
1084impl Serialize for TypeData {
1085    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1086    where
1087        S: Serializer,
1088    {
1089        let mut seq = serializer.serialize_seq(None)?;
1090        let mut buf = Vec::new();
1091        encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf);
1092        let mut serialized_result = Vec::new();
1093        stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result).unwrap();
1094        seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
1095        buf.clear();
1096        serialized_result.clear();
1097        encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf);
1098        stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result).unwrap();
1099        seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
1100        if self.search_unbox {
1101            seq.serialize_element(&1)?;
1102        }
1103        seq.end()
1104    }
1105}
1106
1107impl<'de> Deserialize<'de> for TypeData {
1108    fn deserialize<D>(deserializer: D) -> Result<TypeData, D::Error>
1109    where
1110        D: Deserializer<'de>,
1111    {
1112        struct TypeDataVisitor;
1113        impl<'de> de::Visitor<'de> for TypeDataVisitor {
1114            type Value = TypeData;
1115            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1116                write!(formatter, "type data")
1117            }
1118            fn visit_none<E>(self) -> Result<TypeData, E> {
1119                Ok(TypeData {
1120                    inverted_function_inputs_index: vec![],
1121                    inverted_function_output_index: vec![],
1122                    search_unbox: false,
1123                })
1124            }
1125            fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<TypeData, A::Error> {
1126                let inverted_function_inputs_index: String =
1127                    v.next_element()?.unwrap_or(String::new());
1128                let inverted_function_output_index: String =
1129                    v.next_element()?.unwrap_or(String::new());
1130                let search_unbox: u32 = v.next_element()?.unwrap_or(0);
1131                let mut idx: Vec<u8> = Vec::new();
1132                stringdex_internals::decode::read_base64_from_bytes(
1133                    inverted_function_inputs_index.as_bytes(),
1134                    &mut idx,
1135                )
1136                .unwrap();
1137                let mut inverted_function_inputs_index = Vec::new();
1138                encode::read_postings_from_string(&mut inverted_function_inputs_index, &idx);
1139                idx.clear();
1140                stringdex_internals::decode::read_base64_from_bytes(
1141                    inverted_function_output_index.as_bytes(),
1142                    &mut idx,
1143                )
1144                .unwrap();
1145                let mut inverted_function_output_index = Vec::new();
1146                encode::read_postings_from_string(&mut inverted_function_output_index, &idx);
1147                Ok(TypeData {
1148                    inverted_function_inputs_index,
1149                    inverted_function_output_index,
1150                    search_unbox: search_unbox == 1,
1151                })
1152            }
1153        }
1154        deserializer.deserialize_any(TypeDataVisitor)
1155    }
1156}
1157
1158enum SerializedOptionalString {
1159    None,
1160    Some(String),
1161}
1162
1163impl From<SerializedOptionalString> for Option<String> {
1164    fn from(me: SerializedOptionalString) -> Option<String> {
1165        match me {
1166            SerializedOptionalString::Some(string) => Some(string),
1167            SerializedOptionalString::None => None,
1168        }
1169    }
1170}
1171
1172impl Serialize for SerializedOptionalString {
1173    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1174    where
1175        S: Serializer,
1176    {
1177        match self {
1178            SerializedOptionalString::Some(string) => string.serialize(serializer),
1179            SerializedOptionalString::None => 0.serialize(serializer),
1180        }
1181    }
1182}
1183impl<'de> Deserialize<'de> for SerializedOptionalString {
1184    fn deserialize<D>(deserializer: D) -> Result<SerializedOptionalString, D::Error>
1185    where
1186        D: Deserializer<'de>,
1187    {
1188        struct SerializedOptionalStringVisitor;
1189        impl<'de> de::Visitor<'de> for SerializedOptionalStringVisitor {
1190            type Value = SerializedOptionalString;
1191            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1192                write!(formatter, "0 or string")
1193            }
1194            fn visit_u64<E: de::Error>(self, v: u64) -> Result<SerializedOptionalString, E> {
1195                if v != 0 {
1196                    return Err(E::missing_field("not 0"));
1197                }
1198                Ok(SerializedOptionalString::None)
1199            }
1200            fn visit_string<E: de::Error>(self, v: String) -> Result<SerializedOptionalString, E> {
1201                Ok(SerializedOptionalString::Some(v))
1202            }
1203            fn visit_str<E: de::Error>(self, v: &str) -> Result<SerializedOptionalString, E> {
1204                Ok(SerializedOptionalString::Some(v.to_string()))
1205            }
1206        }
1207        deserializer.deserialize_any(SerializedOptionalStringVisitor)
1208    }
1209}
1210
1211enum SerializedOptional32 {
1212    None,
1213    Some(i32),
1214}
1215
1216impl From<SerializedOptional32> for Option<i32> {
1217    fn from(me: SerializedOptional32) -> Option<i32> {
1218        match me {
1219            SerializedOptional32::Some(number) => Some(number),
1220            SerializedOptional32::None => None,
1221        }
1222    }
1223}
1224
1225impl Serialize for SerializedOptional32 {
1226    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1227    where
1228        S: Serializer,
1229    {
1230        match self {
1231            &SerializedOptional32::Some(number) if number < 0 => number.serialize(serializer),
1232            &SerializedOptional32::Some(number) => (number + 1).serialize(serializer),
1233            &SerializedOptional32::None => 0.serialize(serializer),
1234        }
1235    }
1236}
1237impl<'de> Deserialize<'de> for SerializedOptional32 {
1238    fn deserialize<D>(deserializer: D) -> Result<SerializedOptional32, D::Error>
1239    where
1240        D: Deserializer<'de>,
1241    {
1242        struct SerializedOptional32Visitor;
1243        impl<'de> de::Visitor<'de> for SerializedOptional32Visitor {
1244            type Value = SerializedOptional32;
1245            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1246                write!(formatter, "integer")
1247            }
1248            fn visit_i64<E: de::Error>(self, v: i64) -> Result<SerializedOptional32, E> {
1249                Ok(match v {
1250                    0 => SerializedOptional32::None,
1251                    v if v < 0 => SerializedOptional32::Some(v as i32),
1252                    v => SerializedOptional32::Some(v as i32 - 1),
1253                })
1254            }
1255            fn visit_u64<E: de::Error>(self, v: u64) -> Result<SerializedOptional32, E> {
1256                Ok(match v {
1257                    0 => SerializedOptional32::None,
1258                    v => SerializedOptional32::Some(v as i32 - 1),
1259                })
1260            }
1261        }
1262        deserializer.deserialize_any(SerializedOptional32Visitor)
1263    }
1264}
1265
1266/// Builds the search index from the collected metadata
1267pub(crate) fn build_index(
1268    krate: &clean::Crate,
1269    cache: &mut Cache,
1270    tcx: TyCtxt<'_>,
1271    doc_root: &Path,
1272    resource_suffix: &str,
1273    should_merge: &ShouldMerge,
1274) -> Result<SerializedSearchIndex, Error> {
1275    let mut search_index = std::mem::take(&mut cache.search_index);
1276
1277    // Attach all orphan items to the type's definition if the type
1278    // has since been learned.
1279    for &OrphanImplItem { impl_id, parent, trait_parent, ref item, ref impl_generics } in
1280        &cache.orphan_impl_items
1281    {
1282        if let Some(path_info) = cache.paths.get(&parent) {
1283            let info = IndexItemInfo::new(
1284                tcx,
1285                cache,
1286                item,
1287                Some(parent),
1288                impl_generics.as_ref(),
1289                item.type_(),
1290            );
1291            search_index.push(IndexItem {
1292                defid: item.item_id.as_def_id(),
1293                name: item.name.unwrap(),
1294                module_path: path_info.parts[..path_info.parts.len() - 1].to_vec(),
1295                parent: Some(parent),
1296                parent_idx: None,
1297                trait_parent,
1298                trait_parent_idx: None,
1299                exact_module_path: None,
1300                impl_id,
1301                info,
1302            });
1303        }
1304    }
1305
1306    // Sort search index items. This improves the compressibility of the search index.
1307    search_index.sort_unstable_by(|k1, k2| {
1308        // `sort_unstable_by_key` produces lifetime errors
1309        // HACK(rustdoc): should not be sorting `CrateNum` or `DefIndex`, this will soon go away, too
1310        fn key(i: &IndexItem) -> (&[Symbol], &str, ItemType, Option<(DefIndex, CrateNum)>) {
1311            (&i.module_path, i.name.as_str(), i.info.ty, i.parent.map(|id| (id.index, id.krate)))
1312        }
1313        Ord::cmp(&key(k1), &key(k2))
1314    });
1315
1316    // Now, convert to an on-disk search index format
1317    //
1318    // if there's already a search index, load it into memory and add the new entries to it
1319    // otherwise, do nothing
1320    let mut serialized_index = if should_merge.read_rendered_cci {
1321        SerializedSearchIndex::load(doc_root, resource_suffix)?
1322    } else {
1323        SerializedSearchIndex::default()
1324    };
1325
1326    // The crate always goes first in this list
1327    let crate_name = krate.name(tcx);
1328    let crate_doc =
1329        short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
1330    let crate_idx = {
1331        let crate_path = (ItemType::ExternCrate, vec![crate_name]);
1332        match serialized_index.crate_paths_index.entry(crate_path) {
1333            Entry::Occupied(index) => {
1334                let index = *index.get();
1335                serialized_index.descs[index] = crate_doc;
1336                for type_data in serialized_index.type_data.iter_mut() {
1337                    if let Some(TypeData {
1338                        inverted_function_inputs_index,
1339                        inverted_function_output_index,
1340                        ..
1341                    }) = type_data
1342                    {
1343                        for list in inverted_function_inputs_index
1344                            .iter_mut()
1345                            .chain(inverted_function_output_index.iter_mut())
1346                        {
1347                            list.retain(|fnid| {
1348                                serialized_index.entry_data[usize::try_from(*fnid).unwrap()]
1349                                    .as_ref()
1350                                    .unwrap()
1351                                    .krate
1352                                    != index
1353                            });
1354                        }
1355                    }
1356                }
1357                for i in (index + 1)..serialized_index.entry_data.len() {
1358                    // if this crate has been built before, replace its stuff with new
1359                    if let Some(EntryData { krate, .. }) = serialized_index.entry_data[i]
1360                        && krate == index
1361                    {
1362                        serialized_index.entry_data[i] = None;
1363                        serialized_index.descs[i] = String::new();
1364                        serialized_index.function_data[i] = None;
1365                        if serialized_index.path_data[i].is_none() {
1366                            serialized_index.names[i] = String::new();
1367                        }
1368                    }
1369                    if let Some(alias_pointer) = serialized_index.alias_pointers[i]
1370                        && serialized_index.entry_data[alias_pointer].is_none()
1371                    {
1372                        serialized_index.alias_pointers[i] = None;
1373                        if serialized_index.path_data[i].is_none()
1374                            && serialized_index.entry_data[i].is_none()
1375                        {
1376                            serialized_index.names[i] = String::new();
1377                        }
1378                    }
1379                }
1380                index
1381            }
1382            Entry::Vacant(slot) => {
1383                let krate = serialized_index.names.len();
1384                slot.insert(krate);
1385                serialized_index.push(
1386                    crate_name.as_str().to_string(),
1387                    Some(PathData {
1388                        ty: ItemType::ExternCrate,
1389                        module_path: vec![],
1390                        exact_module_path: None,
1391                    }),
1392                    Some(EntryData {
1393                        krate,
1394                        ty: ItemType::ExternCrate,
1395                        module_path: None,
1396                        exact_module_path: None,
1397                        parent: None,
1398                        trait_parent: None,
1399                        deprecated: false,
1400                        unstable: false,
1401                        associated_item_disambiguator_or_extern_crate_url: None,
1402                    }),
1403                    crate_doc,
1404                    None,
1405                    None,
1406                    None,
1407                );
1408                krate
1409            }
1410        }
1411    };
1412
1413    // First, populate associated item parents and trait parents
1414    let crate_items: Vec<&mut IndexItem> = search_index
1415        .iter_mut()
1416        .map(|item| {
1417            let mut defid_to_rowid = |defid, check_external: bool| {
1418                cache
1419                    .paths
1420                    .get(&defid)
1421                    .map(|info| (&info.parts, info.ty))
1422                    .or_else(|| {
1423                        check_external
1424                            .then(|| {
1425                                cache.external_paths.get(&defid).map(|(parts, ty)| (parts, *ty))
1426                            })
1427                            .flatten()
1428                    })
1429                    .map(|(fqp, ty)| {
1430                        let pathid = serialized_index.names.len();
1431                        match serialized_index.crate_paths_index.entry((ty, fqp.clone())) {
1432                            Entry::Occupied(entry) => *entry.get(),
1433                            Entry::Vacant(entry) => {
1434                                entry.insert(pathid);
1435                                let (name, path) = fqp.split_last().unwrap();
1436                                serialized_index.push_path(
1437                                    name.as_str().to_string(),
1438                                    PathData {
1439                                        ty,
1440                                        module_path: path.to_vec(),
1441                                        exact_module_path: if let Some(exact_path) =
1442                                            cache.exact_paths.get(&defid)
1443                                            && let Some((name2, exact_path)) =
1444                                                exact_path.split_last()
1445                                            && name == name2
1446                                        {
1447                                            Some(exact_path.to_vec())
1448                                        } else {
1449                                            None
1450                                        },
1451                                    },
1452                                );
1453                                usize::try_from(pathid).unwrap()
1454                            }
1455                        }
1456                    })
1457            };
1458            item.parent_idx = item.parent.and_then(|p| defid_to_rowid(p, false));
1459            item.trait_parent_idx = item.trait_parent.and_then(|p| defid_to_rowid(p, true));
1460
1461            if let Some(defid) = item.defid
1462                && item.parent_idx.is_none()
1463            {
1464                // If this is a re-export, retain the original path.
1465                // Associated items don't use this.
1466                // Their parent carries the exact fqp instead.
1467                let exact_fqp = cache
1468                    .exact_paths
1469                    .get(&defid)
1470                    .or_else(|| cache.external_paths.get(&defid).map(|(fqp, _)| fqp));
1471                item.exact_module_path = exact_fqp.and_then(|fqp| {
1472                    // Re-exports only count if the name is exactly the same.
1473                    // This is a size optimization, since it means we only need
1474                    // to store the name once (and the path is re-used for everything
1475                    // exported from this same module). It's also likely to Do
1476                    // What I Mean, since if a re-export changes the name, it might
1477                    // also be a change in semantic meaning.
1478                    if fqp.last() != Some(&item.name) {
1479                        return None;
1480                    }
1481                    let path = if item.info.ty == ItemType::Macro
1482                        && find_attr!(tcx, defid, MacroExport { .. })
1483                    {
1484                        // `#[macro_export]` always exports to the crate root.
1485                        vec![tcx.crate_name(defid.krate)]
1486                    } else {
1487                        if fqp.len() < 2 {
1488                            return None;
1489                        }
1490                        fqp[..fqp.len() - 1].to_vec()
1491                    };
1492                    if path == item.module_path {
1493                        return None;
1494                    }
1495                    Some(path)
1496                });
1497            } else if let Some(parent_idx) = item.parent_idx {
1498                let i = usize::try_from(parent_idx).unwrap();
1499                item.module_path =
1500                    serialized_index.path_data[i].as_ref().unwrap().module_path.clone();
1501                item.exact_module_path =
1502                    serialized_index.path_data[i].as_ref().unwrap().exact_module_path.clone();
1503            }
1504
1505            &mut *item
1506        })
1507        .collect();
1508
1509    // Now, find anywhere that the same name is used for two different items
1510    // these need a disambiguator hash for lints
1511    let mut associated_item_duplicates = FxHashMap::<(usize, ItemType, Symbol), usize>::default();
1512    for item in crate_items.iter().map(|x| &*x) {
1513        if item.impl_id.is_some()
1514            && let Some(parent_idx) = item.parent_idx
1515        {
1516            let count = associated_item_duplicates
1517                .entry((parent_idx, item.info.ty, item.name))
1518                .or_insert(0);
1519            *count += 1;
1520        }
1521    }
1522
1523    // now populate the actual entries, type data, and function data
1524    for item in crate_items {
1525        assert_eq!(
1526            item.parent.is_some(),
1527            item.parent_idx.is_some(),
1528            "`{}` is missing idx",
1529            item.name
1530        );
1531
1532        let module_path = Some(serialized_index.get_id_by_module_path(&item.module_path));
1533        let exact_module_path = item
1534            .exact_module_path
1535            .as_ref()
1536            .map(|path| serialized_index.get_id_by_module_path(path));
1537
1538        let new_entry_id = serialized_index.add_entry(
1539            item.name,
1540            EntryData {
1541                ty: item.info.ty,
1542                parent: item.parent_idx,
1543                trait_parent: item.trait_parent_idx,
1544                module_path,
1545                exact_module_path,
1546                deprecated: item
1547                    .info
1548                    .deprecation
1549                    .is_some_and(|deprecation| deprecation.is_in_effect()),
1550                unstable: item.info.is_unstable,
1551                associated_item_disambiguator_or_extern_crate_url: if let Some(impl_id) =
1552                    item.impl_id
1553                    && let Some(parent_idx) = item.parent_idx
1554                    && associated_item_duplicates
1555                        .get(&(parent_idx, item.info.ty, item.name))
1556                        .copied()
1557                        .unwrap_or(0)
1558                        > 1
1559                {
1560                    Some(render::get_id_for_impl(tcx, ItemId::DefId(impl_id)))
1561                } else if item.info.ty == ItemType::ExternCrate
1562                    && let Some(local_def_id) = item.defid.and_then(|def_id| def_id.as_local())
1563                    && let cnum = tcx.extern_mod_stmt_cnum(local_def_id).unwrap_or(LOCAL_CRATE)
1564                    && let Some(ExternalLocation::Remote { url, is_absolute }) =
1565                        cache.extern_locations.get(&cnum)
1566                    && *is_absolute
1567                {
1568                    Some(format!("{}{}", url, tcx.crate_name(cnum).as_str()))
1569                } else {
1570                    None
1571                },
1572                krate: crate_idx,
1573            },
1574            item.info.desc.to_string(),
1575        );
1576
1577        // Aliases
1578        // -------
1579        for alias in &item.info.aliases {
1580            serialized_index.push_alias(alias.as_str().to_string(), new_entry_id);
1581        }
1582
1583        // Function signature reverse index
1584        // --------------------------------
1585        fn insert_into_map(
1586            ty: ItemType,
1587            path: &[Symbol],
1588            exact_path: Option<&[Symbol]>,
1589            search_unbox: bool,
1590            serialized_index: &mut SerializedSearchIndex,
1591            used_in_function_signature: &mut BTreeSet<isize>,
1592        ) -> RenderTypeId {
1593            let pathid = serialized_index.names.len();
1594            let pathid = match serialized_index.crate_paths_index.entry((ty, path.to_vec())) {
1595                Entry::Occupied(entry) => {
1596                    let id = *entry.get();
1597                    if serialized_index.type_data[id].as_mut().is_none() {
1598                        serialized_index.type_data[id] = Some(TypeData {
1599                            search_unbox,
1600                            inverted_function_inputs_index: Vec::new(),
1601                            inverted_function_output_index: Vec::new(),
1602                        });
1603                    } else if search_unbox {
1604                        serialized_index.type_data[id].as_mut().unwrap().search_unbox = true;
1605                    }
1606                    id
1607                }
1608                Entry::Vacant(entry) => {
1609                    entry.insert(pathid);
1610                    let (name, path) = path.split_last().unwrap();
1611                    serialized_index.push_type(
1612                        name.to_string(),
1613                        PathData {
1614                            ty,
1615                            module_path: path.to_vec(),
1616                            exact_module_path: if let Some(exact_path) = exact_path
1617                                && let Some((name2, exact_path)) = exact_path.split_last()
1618                                && name == name2
1619                            {
1620                                Some(exact_path.to_vec())
1621                            } else {
1622                                None
1623                            },
1624                        },
1625                        TypeData {
1626                            inverted_function_inputs_index: Vec::new(),
1627                            inverted_function_output_index: Vec::new(),
1628                            search_unbox,
1629                        },
1630                    );
1631                    pathid
1632                }
1633            };
1634            used_in_function_signature.insert(isize::try_from(pathid).unwrap());
1635            RenderTypeId::Index(isize::try_from(pathid).unwrap())
1636        }
1637
1638        fn convert_render_type_id(
1639            id: RenderTypeId,
1640            cache: &mut Cache,
1641            serialized_index: &mut SerializedSearchIndex,
1642            used_in_function_signature: &mut BTreeSet<isize>,
1643            tcx: TyCtxt<'_>,
1644        ) -> Option<RenderTypeId> {
1645            use crate::clean::PrimitiveType;
1646            let Cache { ref paths, ref external_paths, ref exact_paths, .. } = *cache;
1647            let search_unbox = match id {
1648                RenderTypeId::Mut => false,
1649                RenderTypeId::DefId(defid) => {
1650                    utils::has_doc_flag(tcx, defid, |d| d.search_unbox.is_some())
1651                }
1652                RenderTypeId::Primitive(
1653                    PrimitiveType::Reference | PrimitiveType::RawPointer | PrimitiveType::Tuple,
1654                ) => true,
1655                RenderTypeId::Primitive(..) => false,
1656                RenderTypeId::AssociatedType(..) => false,
1657                // this bool is only used by `insert_into_map`, so it doesn't matter what we set here
1658                // because Index means we've already inserted into the map
1659                RenderTypeId::Index(_) => false,
1660            };
1661            match id {
1662                RenderTypeId::Mut => Some(insert_into_map(
1663                    ItemType::Keyword,
1664                    &[kw::Mut],
1665                    None,
1666                    search_unbox,
1667                    serialized_index,
1668                    used_in_function_signature,
1669                )),
1670                RenderTypeId::DefId(defid) => {
1671                    if let Some((fqp, item_type)) = paths
1672                        .get(&defid)
1673                        .map(|info| (&info.parts, info.ty))
1674                        .or_else(|| external_paths.get(&defid).map(|(parts, ty)| (parts, *ty)))
1675                    {
1676                        if tcx.lang_items().fn_mut_trait() == Some(defid)
1677                            || tcx.lang_items().fn_once_trait() == Some(defid)
1678                            || tcx.lang_items().fn_trait() == Some(defid)
1679                        {
1680                            let name = *fqp.last().unwrap();
1681                            // Make absolutely sure we use this single, correct path,
1682                            // because search.js needs to match. If we don't do this,
1683                            // there are three different paths that these traits may
1684                            // appear to come from.
1685                            Some(insert_into_map(
1686                                item_type,
1687                                &[sym::core, sym::ops, name],
1688                                Some(&[sym::core, sym::ops, name]),
1689                                search_unbox,
1690                                serialized_index,
1691                                used_in_function_signature,
1692                            ))
1693                        } else {
1694                            let exact_fqp = exact_paths
1695                                .get(&defid)
1696                                .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp))
1697                                .map(|v| &v[..])
1698                                // Re-exports only count if the name is exactly the same.
1699                                // This is a size optimization, since it means we only need
1700                                // to store the name once (and the path is re-used for everything
1701                                // exported from this same module). It's also likely to Do
1702                                // What I Mean, since if a re-export changes the name, it might
1703                                // also be a change in semantic meaning.
1704                                .filter(|this_fqp| this_fqp.last() == fqp.last());
1705                            Some(insert_into_map(
1706                                item_type,
1707                                fqp,
1708                                exact_fqp,
1709                                search_unbox,
1710                                serialized_index,
1711                                used_in_function_signature,
1712                            ))
1713                        }
1714                    } else {
1715                        None
1716                    }
1717                }
1718                RenderTypeId::Primitive(primitive) => {
1719                    let sym = primitive.as_sym();
1720                    Some(insert_into_map(
1721                        ItemType::Primitive,
1722                        &[sym],
1723                        None,
1724                        search_unbox,
1725                        serialized_index,
1726                        used_in_function_signature,
1727                    ))
1728                }
1729                RenderTypeId::Index(index) => {
1730                    used_in_function_signature.insert(index);
1731                    Some(id)
1732                }
1733                RenderTypeId::AssociatedType(sym) => Some(insert_into_map(
1734                    ItemType::AssocType,
1735                    &[sym],
1736                    None,
1737                    search_unbox,
1738                    serialized_index,
1739                    used_in_function_signature,
1740                )),
1741            }
1742        }
1743
1744        fn convert_render_type(
1745            ty: &mut RenderType,
1746            cache: &mut Cache,
1747            serialized_index: &mut SerializedSearchIndex,
1748            used_in_function_signature: &mut BTreeSet<isize>,
1749            tcx: TyCtxt<'_>,
1750        ) {
1751            if let Some(generics) = &mut ty.generics {
1752                for item in generics {
1753                    convert_render_type(
1754                        item,
1755                        cache,
1756                        serialized_index,
1757                        used_in_function_signature,
1758                        tcx,
1759                    );
1760                }
1761            }
1762            if let Some(bindings) = &mut ty.bindings {
1763                bindings.retain_mut(|(associated_type, constraints)| {
1764                    let converted_associated_type = convert_render_type_id(
1765                        *associated_type,
1766                        cache,
1767                        serialized_index,
1768                        used_in_function_signature,
1769                        tcx,
1770                    );
1771                    let Some(converted_associated_type) = converted_associated_type else {
1772                        return false;
1773                    };
1774                    *associated_type = converted_associated_type;
1775                    for constraint in constraints {
1776                        convert_render_type(
1777                            constraint,
1778                            cache,
1779                            serialized_index,
1780                            used_in_function_signature,
1781                            tcx,
1782                        );
1783                    }
1784                    true
1785                });
1786            }
1787            let Some(id) = ty.id else {
1788                assert!(ty.generics.is_some());
1789                return;
1790            };
1791            ty.id = if let RenderTypeId::DefId(def_id) = id
1792                && matches!(tcx.def_kind(def_id), rustc_hir::def::DefKind::OpaqueTy)
1793            {
1794                // We exclude opaque types as they cannot have attributes, so no need to call
1795                // `convert_render_type_id`.
1796                None
1797            } else {
1798                convert_render_type_id(id, cache, serialized_index, used_in_function_signature, tcx)
1799            };
1800            use crate::clean::PrimitiveType;
1801            // These cases are added to the inverted index, but not actually included
1802            // in the signature. There's a matching set of cases in the
1803            // `unifyFunctionTypeIsMatchCandidate` function, for the slow path.
1804            match id {
1805                // typeNameIdOfArrayOrSlice
1806                RenderTypeId::Primitive(PrimitiveType::Array | PrimitiveType::Slice) => {
1807                    insert_into_map(
1808                        ItemType::Primitive,
1809                        &[sym::empty_brackets],
1810                        None,
1811                        false,
1812                        serialized_index,
1813                        used_in_function_signature,
1814                    );
1815                }
1816                RenderTypeId::Primitive(PrimitiveType::Tuple | PrimitiveType::Unit) => {
1817                    // typeNameIdOfArrayOrSlice
1818                    insert_into_map(
1819                        ItemType::Primitive,
1820                        &[sym::empty_parens],
1821                        None,
1822                        false,
1823                        serialized_index,
1824                        used_in_function_signature,
1825                    );
1826                }
1827                // typeNameIdOfHof
1828                RenderTypeId::Primitive(PrimitiveType::Fn) => {
1829                    insert_into_map(
1830                        ItemType::Primitive,
1831                        &[sym::right_arrow],
1832                        None,
1833                        false,
1834                        serialized_index,
1835                        used_in_function_signature,
1836                    );
1837                }
1838                RenderTypeId::DefId(did)
1839                    if tcx.lang_items().fn_mut_trait() == Some(did)
1840                        || tcx.lang_items().fn_once_trait() == Some(did)
1841                        || tcx.lang_items().fn_trait() == Some(did) =>
1842                {
1843                    insert_into_map(
1844                        ItemType::Primitive,
1845                        &[sym::right_arrow],
1846                        None,
1847                        false,
1848                        serialized_index,
1849                        used_in_function_signature,
1850                    );
1851                }
1852                // not special
1853                _ => {}
1854            }
1855        }
1856        if let Some(search_type) = &mut item.info.search_type {
1857            let mut used_in_function_inputs = BTreeSet::new();
1858            let mut used_in_function_output = BTreeSet::new();
1859            for item in &mut search_type.inputs {
1860                convert_render_type(
1861                    item,
1862                    cache,
1863                    &mut serialized_index,
1864                    &mut used_in_function_inputs,
1865                    tcx,
1866                );
1867            }
1868            for item in &mut search_type.output {
1869                convert_render_type(
1870                    item,
1871                    cache,
1872                    &mut serialized_index,
1873                    &mut used_in_function_output,
1874                    tcx,
1875                );
1876            }
1877            let used_in_constraints = search_type
1878                .where_clause
1879                .iter_mut()
1880                .map(|constraint| {
1881                    let mut used_in_constraint = BTreeSet::new();
1882                    for trait_ in constraint {
1883                        convert_render_type(
1884                            trait_,
1885                            cache,
1886                            &mut serialized_index,
1887                            &mut used_in_constraint,
1888                            tcx,
1889                        );
1890                    }
1891                    used_in_constraint
1892                })
1893                .collect::<Vec<_>>();
1894            loop {
1895                let mut inserted_any = false;
1896                for (i, used_in_constraint) in used_in_constraints.iter().enumerate() {
1897                    let id = !(i as isize);
1898                    if used_in_function_inputs.contains(&id)
1899                        && !used_in_function_inputs.is_superset(&used_in_constraint)
1900                    {
1901                        used_in_function_inputs.extend(used_in_constraint.iter().copied());
1902                        inserted_any = true;
1903                    }
1904                    if used_in_function_output.contains(&id)
1905                        && !used_in_function_output.is_superset(&used_in_constraint)
1906                    {
1907                        used_in_function_output.extend(used_in_constraint.iter().copied());
1908                        inserted_any = true;
1909                    }
1910                }
1911                if !inserted_any {
1912                    break;
1913                }
1914            }
1915            let search_type_size = search_type.size() +
1916                // Artificially give struct fields a size of 8 instead of their real
1917                // size of 2. This is because search.js sorts them to the end, so
1918                // by pushing them down, we prevent them from blocking real 2-arity functions.
1919                //
1920                // The number 8 is arbitrary. We want it big, but not enormous,
1921                // because the postings list has to fill in an empty array for each
1922                // unoccupied size.
1923                if item.info.ty.is_fn_like() { 0 } else { 16 };
1924            serialized_index.function_data[new_entry_id] = Some(search_type.clone());
1925
1926            #[derive(Clone, Copy)]
1927            enum InvertedIndexType {
1928                Inputs,
1929                Output,
1930            }
1931            impl InvertedIndexType {
1932                fn from_type_data(self, type_data: &mut TypeData) -> &mut Vec<Vec<u32>> {
1933                    match self {
1934                        Self::Inputs => &mut type_data.inverted_function_inputs_index,
1935                        Self::Output => &mut type_data.inverted_function_output_index,
1936                    }
1937                }
1938            }
1939
1940            let mut process_used_in_function =
1941                |used_in_function: BTreeSet<isize>, index_type: InvertedIndexType| {
1942                    for index in used_in_function {
1943                        let postings = if index >= 0 {
1944                            assert!(serialized_index.path_data[index as usize].is_some());
1945                            index_type.from_type_data(
1946                                serialized_index.type_data[index as usize].as_mut().unwrap(),
1947                            )
1948                        } else {
1949                            let generic_id = index.unsigned_abs() - 1;
1950                            if generic_id >= serialized_index.generic_inverted_index.len() {
1951                                serialized_index
1952                                    .generic_inverted_index
1953                                    .resize(generic_id + 1, Vec::new());
1954                            }
1955                            &mut serialized_index.generic_inverted_index[generic_id]
1956                        };
1957                        if search_type_size >= postings.len() {
1958                            postings.resize(search_type_size + 1, Vec::new());
1959                        }
1960                        let posting = &mut postings[search_type_size];
1961                        if posting.last() != Some(&(new_entry_id as u32)) {
1962                            posting.push(new_entry_id as u32);
1963                        }
1964                    }
1965                };
1966
1967            process_used_in_function(used_in_function_inputs, InvertedIndexType::Inputs);
1968            process_used_in_function(used_in_function_output, InvertedIndexType::Output);
1969        }
1970    }
1971
1972    Ok(serialized_index.sort())
1973}
1974
1975pub(crate) fn get_function_type_for_search(
1976    item: &clean::Item,
1977    tcx: TyCtxt<'_>,
1978    impl_generics: Option<&(clean::Type, clean::Generics)>,
1979    parent: Option<DefId>,
1980    cache: &Cache,
1981) -> Option<IndexItemFunctionType> {
1982    let mut trait_info = None;
1983    let impl_or_trait_generics = impl_generics.or_else(|| {
1984        if let Some(def_id) = parent
1985            && let Some(trait_) = cache.traits.get(&def_id)
1986            && let Some((path, _)) = cache
1987                .paths
1988                .get(&def_id)
1989                .map(|info| (&info.parts, info.ty))
1990                .or_else(|| cache.external_paths.get(&def_id).map(|(parts, ty)| (parts, *ty)))
1991        {
1992            let path = clean::Path {
1993                res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, def_id),
1994                segments: path
1995                    .iter()
1996                    .map(|name| clean::PathSegment {
1997                        name: *name,
1998                        args: clean::GenericArgs::AngleBracketed {
1999                            args: ThinVec::new(),
2000                            constraints: ThinVec::new(),
2001                        },
2002                    })
2003                    .collect(),
2004            };
2005            trait_info = Some((clean::Type::Path { path }, trait_.generics.clone()));
2006            Some(trait_info.as_ref().unwrap())
2007        } else {
2008            None
2009        }
2010    });
2011    let (mut inputs, mut output, param_names, where_clause) = match item.kind {
2012        clean::ForeignFunctionItem(ref f, _)
2013        | clean::FunctionItem(ref f)
2014        | clean::MethodItem(ref f, _)
2015        | clean::RequiredMethodItem(ref f, _) => {
2016            get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
2017        }
2018        clean::ConstantItem(ref c) => make_nullary_fn(&c.type_),
2019        clean::StaticItem(ref s) => make_nullary_fn(&s.type_),
2020        clean::StructFieldItem(ref t) if let Some(parent) = parent => {
2021            let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> =
2022                Default::default();
2023            let output = get_index_type(t, vec![], &mut rgen);
2024            let input = RenderType {
2025                id: Some(RenderTypeId::DefId(parent)),
2026                generics: None,
2027                bindings: None,
2028            };
2029            (vec![input], vec![output], vec![], vec![])
2030        }
2031        _ => return None,
2032    };
2033
2034    inputs.retain(|a| a.id.is_some() || a.generics.is_some());
2035    output.retain(|a| a.id.is_some() || a.generics.is_some());
2036
2037    Some(IndexItemFunctionType { inputs, output, where_clause, param_names })
2038}
2039
2040fn get_index_type(
2041    clean_type: &clean::Type,
2042    generics: Vec<RenderType>,
2043    rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
2044) -> RenderType {
2045    RenderType {
2046        id: get_index_type_id(clean_type, rgen),
2047        generics: if generics.is_empty() { None } else { Some(generics) },
2048        bindings: None,
2049    }
2050}
2051
2052fn get_index_type_id(
2053    clean_type: &clean::Type,
2054    rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
2055) -> Option<RenderTypeId> {
2056    use rustc_hir::def::{DefKind, Res};
2057    match *clean_type {
2058        clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())),
2059        clean::DynTrait(ref bounds, _) => {
2060            bounds.first().map(|b| RenderTypeId::DefId(b.trait_.def_id()))
2061        }
2062        clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
2063        clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)),
2064        clean::RawPointer { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::RawPointer)),
2065        // The type parameters are converted to generics in `simplify_fn_type`
2066        clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)),
2067        clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)),
2068        clean::BareFunction(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Fn)),
2069        clean::Tuple(ref n) if n.is_empty() => {
2070            Some(RenderTypeId::Primitive(clean::PrimitiveType::Unit))
2071        }
2072        clean::Tuple(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Tuple)),
2073        clean::QPath(ref data) => {
2074            if data.self_type.is_self_type()
2075                && let Some(clean::Path { res: Res::Def(DefKind::Trait, trait_), .. }) = data.trait_
2076            {
2077                let idx = -isize::try_from(rgen.len() + 1).unwrap();
2078                let (idx, _) = rgen
2079                    .entry(SimplifiedParam::AssociatedType(trait_, data.assoc.name))
2080                    .or_insert_with(|| (idx, Vec::new()));
2081                Some(RenderTypeId::Index(*idx))
2082            } else {
2083                None
2084            }
2085        }
2086        // Not supported yet
2087        clean::Type::Pat(..)
2088        | clean::Type::FieldOf(..)
2089        | clean::Generic(_)
2090        | clean::SelfTy
2091        | clean::ImplTrait(_)
2092        | clean::Infer
2093        | clean::UnsafeBinder(_) => None,
2094    }
2095}
2096
2097#[derive(Clone, Copy, Eq, Hash, PartialEq)]
2098enum SimplifiedParam {
2099    // other kinds of type parameters are identified by their name
2100    Symbol(Symbol),
2101    // every argument-position impl trait is its own type parameter
2102    Anonymous(isize),
2103    // in a trait definition, the associated types are all bound to
2104    // their own type parameter
2105    AssociatedType(DefId, Symbol),
2106}
2107
2108/// The point of this function is to lower generics and types into the simplified form that the
2109/// frontend search engine can use.
2110///
2111/// For example, `[T, U, i32]]` where you have the bounds: `T: Display, U: Option<T>` will return
2112/// `[-1, -2, i32] where -1: Display, -2: Option<-1>`. If a type parameter has no trait bound, it
2113/// will still get a number. If a constraint is present but not used in the actual types, it will
2114/// not be added to the map.
2115///
2116/// This function also works recursively.
2117#[instrument(level = "trace", skip(tcx, rgen, cache))]
2118fn simplify_fn_type<'a, 'tcx>(
2119    self_: Option<&'a Type>,
2120    generics: &Generics,
2121    arg: &'a Type,
2122    tcx: TyCtxt<'tcx>,
2123    recurse: usize,
2124    rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
2125    is_return: bool,
2126    cache: &Cache,
2127) -> Option<RenderType> {
2128    if recurse >= 10 {
2129        // FIXME: remove this whole recurse thing when the recursion bug is fixed
2130        // See #59502 for the original issue.
2131        return None;
2132    }
2133
2134    // First, check if it's "Self".
2135    let (is_self, arg) = if let Some(self_) = self_
2136        && arg.is_self_type()
2137    {
2138        (true, self_)
2139    } else {
2140        (false, arg)
2141    };
2142
2143    // If this argument is a type parameter and not a trait bound or a type, we need to look
2144    // for its bounds.
2145    match *arg {
2146        Type::Generic(arg_s) => {
2147            // First we check if the bounds are in a `where` predicate...
2148            let where_bounds = generics
2149                .where_predicates
2150                .iter()
2151                .filter_map(|g| {
2152                    if let WherePredicate::BoundPredicate { ty, bounds, .. } = g
2153                        && *ty == *arg
2154                    {
2155                        Some(bounds)
2156                    } else {
2157                        None
2158                    }
2159                })
2160                .flatten();
2161            // Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
2162            let inline_bounds = generics
2163                .params
2164                .iter()
2165                .find(|g| g.is_type() && g.name == arg_s)
2166                .and_then(|bound| bound.get_bounds())
2167                .into_iter()
2168                .flatten();
2169
2170            let type_bounds = where_bounds
2171                .chain(inline_bounds)
2172                .filter_map(
2173                    |bound| if let Some(path) = bound.get_trait_path() { Some(path) } else { None },
2174                )
2175                .filter_map(|path| {
2176                    let ty = Type::Path { path };
2177                    simplify_fn_type(self_, generics, &ty, tcx, recurse + 1, rgen, is_return, cache)
2178                })
2179                .collect();
2180
2181            Some(if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
2182                RenderType { id: Some(RenderTypeId::Index(*idx)), generics: None, bindings: None }
2183            } else {
2184                let idx = -isize::try_from(rgen.len() + 1).unwrap();
2185                rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
2186                RenderType { id: Some(RenderTypeId::Index(idx)), generics: None, bindings: None }
2187            })
2188        }
2189        Type::ImplTrait(ref bounds) => {
2190            let type_bounds = bounds
2191                .iter()
2192                .filter_map(|bound| bound.get_trait_path())
2193                .filter_map(|path| {
2194                    let ty = Type::Path { path };
2195                    simplify_fn_type(self_, generics, &ty, tcx, recurse + 1, rgen, is_return, cache)
2196                })
2197                .collect::<Vec<_>>();
2198            Some(if is_return && !type_bounds.is_empty() {
2199                // In return position, `impl Trait` is a unique thing.
2200                RenderType { id: None, generics: Some(type_bounds), bindings: None }
2201            } else {
2202                // In parameter position, `impl Trait` is the same as an unnamed generic parameter.
2203                let idx = -isize::try_from(rgen.len() + 1).unwrap();
2204                rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
2205                RenderType { id: Some(RenderTypeId::Index(idx)), generics: None, bindings: None }
2206            })
2207        }
2208        Type::Slice(ref ty) => {
2209            let ty_generics =
2210                simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache)
2211                    .into_iter()
2212                    .collect();
2213            Some(get_index_type(arg, ty_generics, rgen))
2214        }
2215        Type::Array(ref ty, _) => {
2216            let ty_generics =
2217                simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache)
2218                    .into_iter()
2219                    .collect();
2220            Some(get_index_type(arg, ty_generics, rgen))
2221        }
2222        Type::Tuple(ref tys) => {
2223            let ty_generics = tys
2224                .iter()
2225                .filter_map(|ty| {
2226                    simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache)
2227                })
2228                .collect();
2229            Some(get_index_type(arg, ty_generics, rgen))
2230        }
2231        Type::BareFunction(ref bf) => {
2232            let ty_generics = bf
2233                .decl
2234                .inputs
2235                .iter()
2236                .map(|arg| &arg.type_)
2237                .filter_map(|ty| {
2238                    simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache)
2239                })
2240                .collect();
2241            // The search index, for simplicity's sake, represents fn pointers and closures
2242            // the same way: as a tuple for the parameters, and an associated type for the
2243            // return type.
2244            let ty_output = simplify_fn_type(
2245                self_,
2246                generics,
2247                &bf.decl.output,
2248                tcx,
2249                recurse + 1,
2250                rgen,
2251                is_return,
2252                cache,
2253            )
2254            .into_iter()
2255            .collect();
2256            let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
2257            Some(RenderType {
2258                id: get_index_type_id(arg, rgen),
2259                bindings: Some(ty_bindings),
2260                generics: Some(ty_generics),
2261            })
2262        }
2263        Type::BorrowedRef { lifetime: _, mutability, ref type_ }
2264        | Type::RawPointer(mutability, ref type_) => {
2265            let mut ty_generics = Vec::new();
2266            if mutability.is_mut() {
2267                ty_generics.push(RenderType {
2268                    id: Some(RenderTypeId::Mut),
2269                    generics: None,
2270                    bindings: None,
2271                });
2272            }
2273            if let Some(ty) =
2274                simplify_fn_type(self_, generics, type_, tcx, recurse + 1, rgen, is_return, cache)
2275            {
2276                ty_generics.push(ty);
2277            }
2278            Some(get_index_type(arg, ty_generics, rgen))
2279        }
2280        _ => {
2281            // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
2282            // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
2283            //
2284            // So in here, we can add it directly and look for its own type parameters (so for `Option`,
2285            // we will look for them but not for `T`).
2286            let mut ty_generics = Vec::new();
2287            let mut ty_constraints = Vec::new();
2288            if let Some(arg_generics) = arg.generic_args() {
2289                ty_generics = arg_generics
2290                    .into_iter()
2291                    .filter_map(|param| match param {
2292                        clean::GenericArg::Type(ty) => Some(ty),
2293                        _ => None,
2294                    })
2295                    .filter_map(|ty| {
2296                        simplify_fn_type(
2297                            self_,
2298                            generics,
2299                            &ty,
2300                            tcx,
2301                            recurse + 1,
2302                            rgen,
2303                            is_return,
2304                            cache,
2305                        )
2306                    })
2307                    .collect();
2308                for constraint in arg_generics.constraints() {
2309                    simplify_fn_constraint(
2310                        self_,
2311                        generics,
2312                        &constraint,
2313                        tcx,
2314                        recurse + 1,
2315                        &mut ty_constraints,
2316                        rgen,
2317                        is_return,
2318                        cache,
2319                    );
2320                }
2321            }
2322            // Every trait associated type on self gets assigned to a type parameter index
2323            // this same one is used later for any appearances of these types
2324            //
2325            // for example, Iterator::next is:
2326            //
2327            //     trait Iterator {
2328            //         fn next(&mut self) -> Option<Self::Item>
2329            //     }
2330            //
2331            // Self is technically just Iterator, but we want to pretend it's more like this:
2332            //
2333            //     fn next<T>(self: Iterator<Item=T>) -> Option<T>
2334            if is_self
2335                && let Type::Path { path } = arg
2336                && let def_id = path.def_id()
2337                && let Some(trait_) = cache.traits.get(&def_id)
2338                && trait_.items.iter().any(|at| at.is_required_associated_type())
2339            {
2340                for assoc_ty in &trait_.items {
2341                    if let clean::ItemKind::RequiredAssocTypeItem(_generics, bounds) =
2342                        &assoc_ty.kind
2343                        && let Some(name) = assoc_ty.name
2344                    {
2345                        let idx = -isize::try_from(rgen.len() + 1).unwrap();
2346                        let (idx, stored_bounds) = rgen
2347                            .entry(SimplifiedParam::AssociatedType(def_id, name))
2348                            .or_insert_with(|| (idx, Vec::new()));
2349                        let idx = *idx;
2350                        if stored_bounds.is_empty() {
2351                            // Can't just pass stored_bounds to simplify_fn_type,
2352                            // because it also accepts rgen as a parameter.
2353                            // Instead, have it fill in this local, then copy it into the map afterward.
2354                            let type_bounds = bounds
2355                                .iter()
2356                                .filter_map(|bound| bound.get_trait_path())
2357                                .filter_map(|path| {
2358                                    let ty = Type::Path { path };
2359                                    simplify_fn_type(
2360                                        self_,
2361                                        generics,
2362                                        &ty,
2363                                        tcx,
2364                                        recurse + 1,
2365                                        rgen,
2366                                        is_return,
2367                                        cache,
2368                                    )
2369                                })
2370                                .collect();
2371                            let stored_bounds = &mut rgen
2372                                .get_mut(&SimplifiedParam::AssociatedType(def_id, name))
2373                                .unwrap()
2374                                .1;
2375                            if stored_bounds.is_empty() {
2376                                *stored_bounds = type_bounds;
2377                            }
2378                        }
2379                        ty_constraints.push((
2380                            RenderTypeId::AssociatedType(name),
2381                            vec![RenderType {
2382                                id: Some(RenderTypeId::Index(idx)),
2383                                generics: None,
2384                                bindings: None,
2385                            }],
2386                        ))
2387                    }
2388                }
2389            }
2390            let id = get_index_type_id(arg, rgen);
2391            if id.is_some() || !ty_generics.is_empty() {
2392                Some(RenderType {
2393                    id,
2394                    bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
2395                    generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
2396                })
2397            } else {
2398                None
2399            }
2400        }
2401    }
2402}
2403
2404fn simplify_fn_constraint<'a>(
2405    self_: Option<&'a Type>,
2406    generics: &Generics,
2407    constraint: &'a clean::AssocItemConstraint,
2408    tcx: TyCtxt<'_>,
2409    recurse: usize,
2410    res: &mut Vec<(RenderTypeId, Vec<RenderType>)>,
2411    rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
2412    is_return: bool,
2413    cache: &Cache,
2414) {
2415    let mut ty_constraints = Vec::new();
2416    let ty_constrained_assoc = RenderTypeId::AssociatedType(constraint.assoc.name);
2417    for param in &constraint.assoc.args {
2418        match param {
2419            clean::GenericArg::Type(arg) => {
2420                ty_constraints.extend(simplify_fn_type(
2421                    self_,
2422                    generics,
2423                    &arg,
2424                    tcx,
2425                    recurse + 1,
2426                    rgen,
2427                    is_return,
2428                    cache,
2429                ));
2430            }
2431            clean::GenericArg::Lifetime(_)
2432            | clean::GenericArg::Const(_)
2433            | clean::GenericArg::Infer => {}
2434        }
2435    }
2436    for constraint in constraint.assoc.args.constraints() {
2437        simplify_fn_constraint(
2438            self_,
2439            generics,
2440            &constraint,
2441            tcx,
2442            recurse + 1,
2443            res,
2444            rgen,
2445            is_return,
2446            cache,
2447        );
2448    }
2449    match &constraint.kind {
2450        clean::AssocItemConstraintKind::Equality { term } => {
2451            if let clean::Term::Type(arg) = &term {
2452                ty_constraints.extend(simplify_fn_type(
2453                    self_,
2454                    generics,
2455                    arg,
2456                    tcx,
2457                    recurse + 1,
2458                    rgen,
2459                    is_return,
2460                    cache,
2461                ));
2462            }
2463        }
2464        clean::AssocItemConstraintKind::Bound { bounds } => {
2465            for bound in &bounds[..] {
2466                if let Some(path) = bound.get_trait_path() {
2467                    let ty = Type::Path { path };
2468                    ty_constraints.extend(simplify_fn_type(
2469                        self_,
2470                        generics,
2471                        &ty,
2472                        tcx,
2473                        recurse + 1,
2474                        rgen,
2475                        is_return,
2476                        cache,
2477                    ));
2478                }
2479            }
2480        }
2481    }
2482    res.push((ty_constrained_assoc, ty_constraints));
2483}
2484
2485/// Create a fake nullary function.
2486///
2487/// Used to allow type-based search on constants and statics.
2488fn make_nullary_fn(
2489    clean_type: &clean::Type,
2490) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
2491    let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
2492    let output = get_index_type(clean_type, vec![], &mut rgen);
2493    (vec![], vec![output], vec![], vec![])
2494}
2495
2496/// Return the full list of types when bounds have been resolved.
2497///
2498/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
2499/// `[u32, Display, Option]`.
2500fn get_fn_inputs_and_outputs(
2501    func: &Function,
2502    tcx: TyCtxt<'_>,
2503    impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>,
2504    cache: &Cache,
2505) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
2506    let decl = &func.decl;
2507
2508    let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
2509
2510    let combined_generics;
2511    let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_or_trait_generics {
2512        match (impl_generics.is_empty(), func.generics.is_empty()) {
2513            (true, _) => (Some(impl_self), &func.generics),
2514            (_, true) => (Some(impl_self), impl_generics),
2515            (false, false) => {
2516                let params =
2517                    func.generics.params.iter().chain(&impl_generics.params).cloned().collect();
2518                let where_predicates = func
2519                    .generics
2520                    .where_predicates
2521                    .iter()
2522                    .chain(&impl_generics.where_predicates)
2523                    .cloned()
2524                    .collect();
2525                combined_generics = clean::Generics { params, where_predicates };
2526                (Some(impl_self), &combined_generics)
2527            }
2528        }
2529    } else {
2530        (None, &func.generics)
2531    };
2532
2533    let param_types = decl
2534        .inputs
2535        .iter()
2536        .filter_map(|param| {
2537            simplify_fn_type(self_, generics, &param.type_, tcx, 0, &mut rgen, false, cache)
2538        })
2539        .collect();
2540
2541    let ret_types = simplify_fn_type(self_, generics, &decl.output, tcx, 0, &mut rgen, true, cache)
2542        .into_iter()
2543        .collect();
2544
2545    let mut simplified_params = rgen.into_iter().collect::<Vec<_>>();
2546    simplified_params.sort_by_key(|(_, (idx, _))| -idx);
2547    (
2548        param_types,
2549        ret_types,
2550        simplified_params
2551            .iter()
2552            .map(|(name, (_idx, _traits))| match name {
2553                SimplifiedParam::Symbol(name) => Some(*name),
2554                SimplifiedParam::Anonymous(_) => None,
2555                SimplifiedParam::AssociatedType(def_id, name) => {
2556                    Some(Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name)))
2557                }
2558            })
2559            .collect(),
2560        simplified_params.into_iter().map(|(_name, (_idx, traits))| traits).collect(),
2561    )
2562}