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