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