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