rustdoc/html/render/
search_index.rs

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