rustdoc/html/render/
search_index.rs

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