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