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