rustdoc/html/render/
search_index.rs

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