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 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 type_data: Vec<Option<TypeData>>,
39 generic_inverted_index: Vec<Vec<Vec<u32>>>,
51 #[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 let mut crate_paths_index: FxHashMap<(ItemType, Vec<Symbol>), usize> = FxHashMap::default();
177 for (i, (name, path_data)) in names.iter().zip(path_data.iter()).enumerate() {
178 if let Some(path_data) = path_data {
179 let full_path = if path_data.module_path.is_empty() {
180 vec![Symbol::intern(name)]
181 } else {
182 let mut full_path = path_data.module_path.to_vec();
183 full_path.push(Symbol::intern(name));
184 full_path
185 };
186 crate_paths_index.insert((path_data.ty, full_path), i);
187 }
188 }
189
190 Ok(SerializedSearchIndex {
191 names,
192 path_data,
193 entry_data,
194 descs,
195 function_data,
196 type_data,
197 alias_pointers,
198 generic_inverted_index,
199 crate_paths_index,
200 })
201 }
202 fn push(
203 &mut self,
204 name: String,
205 path_data: Option<PathData>,
206 entry_data: Option<EntryData>,
207 desc: String,
208 function_data: Option<FunctionData>,
209 type_data: Option<TypeData>,
210 alias_pointer: Option<usize>,
211 ) -> usize {
212 let index = self.names.len();
213 assert_eq!(self.names.len(), self.path_data.len());
214 if let Some(path_data) = &path_data
215 && let name = Symbol::intern(&name)
216 && let fqp = if path_data.module_path.is_empty() {
217 vec![name]
218 } else {
219 let mut v = path_data.module_path.clone();
220 v.push(name);
221 v
222 }
223 && let Some(&other_path) = self.crate_paths_index.get(&(path_data.ty, fqp))
224 && self.path_data.get(other_path).map_or(false, Option::is_some)
225 {
226 self.path_data.push(None);
227 } else {
228 self.path_data.push(path_data);
229 }
230 self.names.push(name);
231 assert_eq!(self.entry_data.len(), self.descs.len());
232 self.entry_data.push(entry_data);
233 assert_eq!(self.descs.len(), self.function_data.len());
234 self.descs.push(desc);
235 assert_eq!(self.function_data.len(), self.type_data.len());
236 self.function_data.push(function_data);
237 assert_eq!(self.type_data.len(), self.alias_pointers.len());
238 self.type_data.push(type_data);
239 self.alias_pointers.push(alias_pointer);
240 index
241 }
242 fn push_path(&mut self, name: String, path_data: PathData) -> usize {
243 self.push(name, Some(path_data), None, String::new(), None, None, None)
244 }
245 fn push_type(&mut self, name: String, path_data: PathData, type_data: TypeData) -> usize {
246 self.push(name, Some(path_data), None, String::new(), None, Some(type_data), None)
247 }
248 fn push_alias(&mut self, name: String, alias_pointer: usize) -> usize {
249 self.push(name, None, None, String::new(), None, None, Some(alias_pointer))
250 }
251
252 fn get_id_by_module_path(&mut self, path: &[Symbol]) -> usize {
253 let ty = if path.len() == 1 { ItemType::ExternCrate } else { ItemType::Module };
254 match self.crate_paths_index.entry((ty, path.to_vec())) {
255 Entry::Occupied(index) => *index.get(),
256 Entry::Vacant(slot) => {
257 slot.insert(self.path_data.len());
258 let (name, module_path) = path.split_last().unwrap();
259 self.push_path(
260 name.as_str().to_string(),
261 PathData { ty, module_path: module_path.to_vec(), exact_module_path: None },
262 )
263 }
264 }
265 }
266
267 pub(crate) fn union(mut self, other: &SerializedSearchIndex) -> SerializedSearchIndex {
268 let other_entryid_offset = self.names.len();
269 let mut map_other_pathid_to_self_pathid: Vec<usize> = Vec::new();
270 let mut skips = FxHashSet::default();
271 for (other_pathid, other_path_data) in other.path_data.iter().enumerate() {
272 if let Some(other_path_data) = other_path_data {
273 let mut fqp = other_path_data.module_path.clone();
274 let name = Symbol::intern(&other.names[other_pathid]);
275 fqp.push(name);
276 let self_pathid = other_entryid_offset + other_pathid;
277 let self_pathid = match self.crate_paths_index.entry((other_path_data.ty, fqp)) {
278 Entry::Vacant(slot) => {
279 slot.insert(self_pathid);
280 self_pathid
281 }
282 Entry::Occupied(existing_entryid) => {
283 skips.insert(other_pathid);
284 let self_pathid = *existing_entryid.get();
285 let new_type_data = match (
286 self.type_data[self_pathid].take(),
287 other.type_data[other_pathid].as_ref(),
288 ) {
289 (Some(self_type_data), None) => Some(self_type_data),
290 (None, Some(other_type_data)) => Some(TypeData {
291 search_unbox: other_type_data.search_unbox,
292 inverted_function_signature_index: other_type_data
293 .inverted_function_signature_index
294 .iter()
295 .cloned()
296 .map(|mut list: Vec<u32>| {
297 for fnid in &mut list {
298 assert!(
299 other.function_data
300 [usize::try_from(*fnid).unwrap()]
301 .is_some(),
302 );
303 *fnid += u32::try_from(other_entryid_offset).unwrap();
306 }
307 list
308 })
309 .collect(),
310 }),
311 (Some(mut self_type_data), Some(other_type_data)) => {
312 for (size, other_list) in other_type_data
313 .inverted_function_signature_index
314 .iter()
315 .enumerate()
316 {
317 while self_type_data.inverted_function_signature_index.len()
318 <= size
319 {
320 self_type_data
321 .inverted_function_signature_index
322 .push(Vec::new());
323 }
324 self_type_data.inverted_function_signature_index[size].extend(
325 other_list.iter().copied().map(|fnid| {
326 assert!(
327 other.function_data[usize::try_from(fnid).unwrap()]
328 .is_some(),
329 );
330 fnid + u32::try_from(other_entryid_offset).unwrap()
333 }),
334 )
335 }
336 Some(self_type_data)
337 }
338 (None, None) => None,
339 };
340 self.type_data[self_pathid] = new_type_data;
341 self_pathid
342 }
343 };
344 map_other_pathid_to_self_pathid.push(self_pathid);
345 } else {
346 map_other_pathid_to_self_pathid.push(!0);
350 }
351 }
352 for other_entryid in 0..other.names.len() {
353 if skips.contains(&other_entryid) {
354 self.push(String::new(), None, None, String::new(), None, None, None);
356 } else {
357 self.push(
358 other.names[other_entryid].clone(),
359 other.path_data[other_entryid].clone(),
360 other.entry_data[other_entryid].as_ref().map(|other_entry_data| EntryData {
361 parent: other_entry_data
362 .parent
363 .map(|parent| map_other_pathid_to_self_pathid[parent])
364 .clone(),
365 module_path: other_entry_data
366 .module_path
367 .map(|path| map_other_pathid_to_self_pathid[path])
368 .clone(),
369 exact_module_path: other_entry_data
370 .exact_module_path
371 .map(|exact_path| map_other_pathid_to_self_pathid[exact_path])
372 .clone(),
373 krate: map_other_pathid_to_self_pathid[other_entry_data.krate],
374 ..other_entry_data.clone()
375 }),
376 other.descs[other_entryid].clone(),
377 other.function_data[other_entryid].as_ref().map(|function_data| FunctionData {
378 function_signature: {
379 let (mut func, _offset) =
380 IndexItemFunctionType::read_from_string_without_param_names(
381 function_data.function_signature.as_bytes(),
382 );
383 fn map_fn_sig_item(
384 map_other_pathid_to_self_pathid: &mut Vec<usize>,
385 ty: &mut RenderType,
386 ) {
387 match ty.id {
388 None => {}
389 Some(RenderTypeId::Index(generic)) if generic < 0 => {}
390 Some(RenderTypeId::Index(id)) => {
391 let id = usize::try_from(id).unwrap();
392 let id = map_other_pathid_to_self_pathid[id];
393 assert!(id != !0);
394 ty.id =
395 Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
396 }
397 _ => unreachable!(),
398 }
399 if let Some(generics) = &mut ty.generics {
400 for generic in generics {
401 map_fn_sig_item(map_other_pathid_to_self_pathid, generic);
402 }
403 }
404 if let Some(bindings) = &mut ty.bindings {
405 for (param, constraints) in bindings {
406 *param = match *param {
407 param @ RenderTypeId::Index(generic) if generic < 0 => {
408 param
409 }
410 RenderTypeId::Index(id) => {
411 let id = usize::try_from(id).unwrap();
412 let id = map_other_pathid_to_self_pathid[id];
413 assert!(id != !0);
414 RenderTypeId::Index(isize::try_from(id).unwrap())
415 }
416 _ => unreachable!(),
417 };
418 for constraint in constraints {
419 map_fn_sig_item(
420 map_other_pathid_to_self_pathid,
421 constraint,
422 );
423 }
424 }
425 }
426 }
427 for input in &mut func.inputs {
428 map_fn_sig_item(&mut map_other_pathid_to_self_pathid, input);
429 }
430 for output in &mut func.output {
431 map_fn_sig_item(&mut map_other_pathid_to_self_pathid, output);
432 }
433 for clause in &mut func.where_clause {
434 for entry in clause {
435 map_fn_sig_item(&mut map_other_pathid_to_self_pathid, entry);
436 }
437 }
438 let mut result =
439 String::with_capacity(function_data.function_signature.len());
440 func.write_to_string_without_param_names(&mut result);
441 result
442 },
443 param_names: function_data.param_names.clone(),
444 }),
445 other.type_data[other_entryid].as_ref().map(|type_data| TypeData {
446 inverted_function_signature_index: type_data
447 .inverted_function_signature_index
448 .iter()
449 .cloned()
450 .map(|mut list| {
451 for fnid in &mut list {
452 assert!(
453 other.function_data[usize::try_from(*fnid).unwrap()]
454 .is_some(),
455 );
456 *fnid += u32::try_from(other_entryid_offset).unwrap();
459 }
460 list
461 })
462 .collect(),
463 search_unbox: type_data.search_unbox,
464 }),
465 other.alias_pointers[other_entryid]
466 .map(|alias_pointer| alias_pointer + other_entryid_offset),
467 );
468 }
469 }
470 for (i, other_generic_inverted_index) in other.generic_inverted_index.iter().enumerate() {
471 for (size, other_list) in other_generic_inverted_index.iter().enumerate() {
472 let self_generic_inverted_index = match self.generic_inverted_index.get_mut(i) {
473 Some(self_generic_inverted_index) => self_generic_inverted_index,
474 None => {
475 self.generic_inverted_index.push(Vec::new());
476 self.generic_inverted_index.last_mut().unwrap()
477 }
478 };
479 while self_generic_inverted_index.len() <= size {
480 self_generic_inverted_index.push(Vec::new());
481 }
482 self_generic_inverted_index[size].extend(
483 other_list
484 .iter()
485 .copied()
486 .map(|fnid| fnid + u32::try_from(other_entryid_offset).unwrap()),
487 );
488 }
489 }
490 self
491 }
492
493 pub(crate) fn sort(self) -> SerializedSearchIndex {
494 let mut idlist: Vec<usize> = (0..self.names.len()).collect();
495 idlist.sort_by_key(|&id| {
498 (
499 self.names[id].is_empty(),
500 self.names[id].len(),
501 &self.names[id],
502 self.entry_data[id].as_ref().map_or("", |entry| self.names[entry.krate].as_str()),
503 self.path_data[id].as_ref().map_or(&[][..], |entry| &entry.module_path[..]),
504 )
505 });
506 let map = FxHashMap::from_iter(
507 idlist.iter().enumerate().map(|(new_id, &old_id)| (old_id, new_id)),
508 );
509 let mut new = SerializedSearchIndex::default();
510 for &id in &idlist {
511 if self.names[id].is_empty() {
512 break;
513 }
514 new.push(
515 self.names[id].clone(),
516 self.path_data[id].clone(),
517 self.entry_data[id].as_ref().map(
518 |EntryData {
519 krate,
520 ty,
521 module_path,
522 exact_module_path,
523 parent,
524 deprecated,
525 is_unstable,
526 associated_item_disambiguator,
527 }| EntryData {
528 krate: *map.get(krate).unwrap(),
529 ty: *ty,
530 module_path: module_path.and_then(|path_id| map.get(&path_id).copied()),
531 exact_module_path: exact_module_path
532 .and_then(|path_id| map.get(&path_id).copied()),
533 parent: parent.and_then(|path_id| map.get(&path_id).copied()),
534 deprecated: *deprecated,
535 is_unstable: *is_unstable,
536 associated_item_disambiguator: associated_item_disambiguator.clone(),
537 },
538 ),
539 self.descs[id].clone(),
540 self.function_data[id].as_ref().map(
541 |FunctionData { function_signature, param_names }| FunctionData {
542 function_signature: {
543 let (mut func, _offset) =
544 IndexItemFunctionType::read_from_string_without_param_names(
545 function_signature.as_bytes(),
546 );
547 fn map_fn_sig_item(map: &FxHashMap<usize, usize>, ty: &mut RenderType) {
548 match ty.id {
549 None => {}
550 Some(RenderTypeId::Index(generic)) if generic < 0 => {}
551 Some(RenderTypeId::Index(id)) => {
552 let id = usize::try_from(id).unwrap();
553 let id = *map.get(&id).unwrap();
554 assert!(id != !0);
555 ty.id =
556 Some(RenderTypeId::Index(isize::try_from(id).unwrap()));
557 }
558 _ => unreachable!(),
559 }
560 if let Some(generics) = &mut ty.generics {
561 for generic in generics {
562 map_fn_sig_item(map, generic);
563 }
564 }
565 if let Some(bindings) = &mut ty.bindings {
566 for (param, constraints) in bindings {
567 *param = match *param {
568 param @ RenderTypeId::Index(generic) if generic < 0 => {
569 param
570 }
571 RenderTypeId::Index(id) => {
572 let id = usize::try_from(id).unwrap();
573 let id = *map.get(&id).unwrap();
574 assert!(id != !0);
575 RenderTypeId::Index(isize::try_from(id).unwrap())
576 }
577 _ => unreachable!(),
578 };
579 for constraint in constraints {
580 map_fn_sig_item(map, constraint);
581 }
582 }
583 }
584 }
585 for input in &mut func.inputs {
586 map_fn_sig_item(&map, input);
587 }
588 for output in &mut func.output {
589 map_fn_sig_item(&map, output);
590 }
591 for clause in &mut func.where_clause {
592 for entry in clause {
593 map_fn_sig_item(&map, entry);
594 }
595 }
596 let mut result = String::with_capacity(function_signature.len());
597 func.write_to_string_without_param_names(&mut result);
598 result
599 },
600 param_names: param_names.clone(),
601 },
602 ),
603 self.type_data[id].as_ref().map(
604 |TypeData { search_unbox, inverted_function_signature_index }| {
605 let inverted_function_signature_index: Vec<Vec<u32>> =
606 inverted_function_signature_index
607 .iter()
608 .cloned()
609 .map(|mut list| {
610 for id in &mut list {
611 *id = u32::try_from(
612 *map.get(&usize::try_from(*id).unwrap()).unwrap(),
613 )
614 .unwrap();
615 }
616 list.sort();
617 list
618 })
619 .collect();
620 TypeData { search_unbox: *search_unbox, inverted_function_signature_index }
621 },
622 ),
623 self.alias_pointers[id].and_then(|alias| map.get(&alias).copied()),
624 );
625 }
626 new.generic_inverted_index = self
627 .generic_inverted_index
628 .into_iter()
629 .map(|mut postings| {
630 for list in postings.iter_mut() {
631 let mut new_list: Vec<u32> = list
632 .iter()
633 .copied()
634 .filter_map(|id| u32::try_from(*map.get(&usize::try_from(id).ok()?)?).ok())
635 .collect();
636 new_list.sort();
637 *list = new_list;
638 }
639 postings
640 })
641 .collect();
642 new
643 }
644
645 pub(crate) fn write_to(self, doc_root: &Path, resource_suffix: &str) -> Result<(), Error> {
646 let SerializedSearchIndex {
647 names,
648 path_data,
649 entry_data,
650 descs,
651 function_data,
652 type_data,
653 alias_pointers,
654 generic_inverted_index,
655 crate_paths_index: _,
656 } = self;
657 let mut serialized_root = Vec::new();
658 serialized_root.extend_from_slice(br#"rr_('{"normalizedName":{"I":""#);
659 let normalized_names = names
660 .iter()
661 .map(|name| {
662 if name.contains("_") {
663 name.replace("_", "").to_ascii_lowercase()
664 } else {
665 name.to_ascii_lowercase()
666 }
667 })
668 .collect::<Vec<String>>();
669 let names_search_tree = stringdex_internals::tree::encode_search_tree_ukkonen(
670 normalized_names.iter().map(|name| name.as_bytes()),
671 );
672 let dir_path = doc_root.join(format!("search.index/"));
673 let _ = std::fs::remove_dir_all(&dir_path); stringdex_internals::write_tree_to_disk(
675 &names_search_tree,
676 &dir_path,
677 &mut serialized_root,
678 )
679 .map_err(|error| Error {
680 file: dir_path,
681 error: format!("failed to write name tree to disk: {error}"),
682 })?;
683 std::mem::drop(names_search_tree);
684 serialized_root.extend_from_slice(br#"","#);
685 serialized_root.extend_from_slice(&perform_write_strings(
686 doc_root,
687 "normalizedName",
688 normalized_names.into_iter(),
689 )?);
690 serialized_root.extend_from_slice(br#"},"crateNames":{"#);
691 let mut crates: Vec<&[u8]> = entry_data
692 .iter()
693 .filter_map(|entry_data| Some(names[entry_data.as_ref()?.krate].as_bytes()))
694 .collect();
695 crates.sort();
696 crates.dedup();
697 serialized_root.extend_from_slice(&perform_write_strings(
698 doc_root,
699 "crateNames",
700 crates.into_iter(),
701 )?);
702 serialized_root.extend_from_slice(br#"},"name":{"#);
703 serialized_root.extend_from_slice(&perform_write_strings(doc_root, "name", names.iter())?);
704 serialized_root.extend_from_slice(br#"},"path":{"#);
705 serialized_root.extend_from_slice(&perform_write_serde(doc_root, "path", path_data)?);
706 serialized_root.extend_from_slice(br#"},"entry":{"#);
707 serialized_root.extend_from_slice(&perform_write_serde(doc_root, "entry", entry_data)?);
708 serialized_root.extend_from_slice(br#"},"desc":{"#);
709 serialized_root.extend_from_slice(&perform_write_strings(
710 doc_root,
711 "desc",
712 descs.into_iter(),
713 )?);
714 serialized_root.extend_from_slice(br#"},"function":{"#);
715 serialized_root.extend_from_slice(&perform_write_serde(
716 doc_root,
717 "function",
718 function_data,
719 )?);
720 serialized_root.extend_from_slice(br#"},"type":{"#);
721 serialized_root.extend_from_slice(&perform_write_serde(doc_root, "type", type_data)?);
722 serialized_root.extend_from_slice(br#"},"alias":{"#);
723 serialized_root.extend_from_slice(&perform_write_serde(doc_root, "alias", alias_pointers)?);
724 serialized_root.extend_from_slice(br#"},"generic_inverted_index":{"#);
725 serialized_root.extend_from_slice(&perform_write_postings(
726 doc_root,
727 "generic_inverted_index",
728 generic_inverted_index,
729 )?);
730 serialized_root.extend_from_slice(br#"}}')"#);
731 fn perform_write_strings(
732 doc_root: &Path,
733 dirname: &str,
734 mut column: impl Iterator<Item = impl AsRef<[u8]> + Clone> + ExactSizeIterator,
735 ) -> Result<Vec<u8>, Error> {
736 let dir_path = doc_root.join(format!("search.index/{dirname}"));
737 stringdex_internals::write_data_to_disk(&mut column, &dir_path).map_err(|error| Error {
738 file: dir_path,
739 error: format!("failed to write column to disk: {error}"),
740 })
741 }
742 fn perform_write_serde(
743 doc_root: &Path,
744 dirname: &str,
745 column: Vec<Option<impl Serialize>>,
746 ) -> Result<Vec<u8>, Error> {
747 perform_write_strings(
748 doc_root,
749 dirname,
750 column.into_iter().map(|value| {
751 if let Some(value) = value {
752 serde_json::to_vec(&value).unwrap()
753 } else {
754 Vec::new()
755 }
756 }),
757 )
758 }
759 fn perform_write_postings(
760 doc_root: &Path,
761 dirname: &str,
762 column: Vec<Vec<Vec<u32>>>,
763 ) -> Result<Vec<u8>, Error> {
764 perform_write_strings(
765 doc_root,
766 dirname,
767 column.into_iter().map(|postings| {
768 let mut buf = Vec::new();
769 encode::write_postings_to_string(&postings, &mut buf);
770 buf
771 }),
772 )
773 }
774 std::fs::write(
775 doc_root.join(format!("search.index/root{resource_suffix}.js")),
776 serialized_root,
777 )
778 .map_err(|error| Error {
779 file: doc_root.join(format!("search.index/root{resource_suffix}.js")),
780 error: format!("failed to write root to disk: {error}"),
781 })?;
782 Ok(())
783 }
784}
785
786#[derive(Clone, Debug)]
787struct EntryData {
788 krate: usize,
789 ty: ItemType,
790 module_path: Option<usize>,
791 exact_module_path: Option<usize>,
792 parent: Option<usize>,
793 deprecated: bool,
794 is_unstable: bool,
795 associated_item_disambiguator: Option<String>,
796}
797
798impl Serialize for EntryData {
799 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
800 where
801 S: Serializer,
802 {
803 let mut seq = serializer.serialize_seq(None)?;
804 seq.serialize_element(&self.krate)?;
805 seq.serialize_element(&self.ty)?;
806 seq.serialize_element(&self.module_path.map(|id| id + 1).unwrap_or(0))?;
807 seq.serialize_element(&self.exact_module_path.map(|id| id + 1).unwrap_or(0))?;
808 seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?;
809 seq.serialize_element(&if self.deprecated { 1 } else { 0 })?;
810 seq.serialize_element(&if self.is_unstable { 1 } else { 0 })?;
811 if let Some(disambig) = &self.associated_item_disambiguator {
812 seq.serialize_element(&disambig)?;
813 }
814 seq.end()
815 }
816}
817
818impl<'de> Deserialize<'de> for EntryData {
819 fn deserialize<D>(deserializer: D) -> Result<EntryData, D::Error>
820 where
821 D: Deserializer<'de>,
822 {
823 struct EntryDataVisitor;
824 impl<'de> de::Visitor<'de> for EntryDataVisitor {
825 type Value = EntryData;
826 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
827 write!(formatter, "path data")
828 }
829 fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<EntryData, A::Error> {
830 let krate: usize =
831 v.next_element()?.ok_or_else(|| A::Error::missing_field("krate"))?;
832 let ty: ItemType =
833 v.next_element()?.ok_or_else(|| A::Error::missing_field("ty"))?;
834 let module_path: SerializedOptional32 =
835 v.next_element()?.ok_or_else(|| A::Error::missing_field("module_path"))?;
836 let exact_module_path: SerializedOptional32 = v
837 .next_element()?
838 .ok_or_else(|| A::Error::missing_field("exact_module_path"))?;
839 let parent: SerializedOptional32 =
840 v.next_element()?.ok_or_else(|| A::Error::missing_field("parent"))?;
841 let deprecated: u32 = v.next_element()?.unwrap_or(0);
842 let is_unstable: u32 = v.next_element()?.unwrap_or(0);
843 let associated_item_disambiguator: Option<String> = v.next_element()?;
844 Ok(EntryData {
845 krate,
846 ty,
847 module_path: Option::<i32>::from(module_path).map(|path| path as usize),
848 exact_module_path: Option::<i32>::from(exact_module_path)
849 .map(|path| path as usize),
850 parent: Option::<i32>::from(parent).map(|path| path as usize),
851 deprecated: deprecated != 0,
852 is_unstable: is_unstable != 0,
853 associated_item_disambiguator,
854 })
855 }
856 }
857 deserializer.deserialize_any(EntryDataVisitor)
858 }
859}
860
861#[derive(Clone, Debug)]
862struct PathData {
863 ty: ItemType,
864 module_path: Vec<Symbol>,
865 exact_module_path: Option<Vec<Symbol>>,
866}
867
868impl Serialize for PathData {
869 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
870 where
871 S: Serializer,
872 {
873 let mut seq = serializer.serialize_seq(None)?;
874 seq.serialize_element(&self.ty)?;
875 seq.serialize_element(&if self.module_path.is_empty() {
876 String::new()
877 } else {
878 join_path_syms(&self.module_path)
879 })?;
880 if let Some(ref path) = self.exact_module_path {
881 seq.serialize_element(&if path.is_empty() {
882 String::new()
883 } else {
884 join_path_syms(path)
885 })?;
886 }
887 seq.end()
888 }
889}
890
891impl<'de> Deserialize<'de> for PathData {
892 fn deserialize<D>(deserializer: D) -> Result<PathData, D::Error>
893 where
894 D: Deserializer<'de>,
895 {
896 struct PathDataVisitor;
897 impl<'de> de::Visitor<'de> for PathDataVisitor {
898 type Value = PathData;
899 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
900 write!(formatter, "path data")
901 }
902 fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<PathData, A::Error> {
903 let ty: ItemType =
904 v.next_element()?.ok_or_else(|| A::Error::missing_field("ty"))?;
905 let module_path: String =
906 v.next_element()?.ok_or_else(|| A::Error::missing_field("module_path"))?;
907 let exact_module_path: Option<String> =
908 v.next_element()?.and_then(SerializedOptionalString::into);
909 Ok(PathData {
910 ty,
911 module_path: if module_path.is_empty() {
912 vec![]
913 } else {
914 module_path.split("::").map(Symbol::intern).collect()
915 },
916 exact_module_path: exact_module_path.map(|path| {
917 if path.is_empty() {
918 vec![]
919 } else {
920 path.split("::").map(Symbol::intern).collect()
921 }
922 }),
923 })
924 }
925 }
926 deserializer.deserialize_any(PathDataVisitor)
927 }
928}
929
930#[derive(Clone, Debug)]
931struct TypeData {
932 search_unbox: bool,
943 inverted_function_signature_index: Vec<Vec<u32>>,
955}
956
957impl Serialize for TypeData {
958 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
959 where
960 S: Serializer,
961 {
962 if self.search_unbox || !self.inverted_function_signature_index.is_empty() {
963 let mut seq = serializer.serialize_seq(None)?;
964 if !self.inverted_function_signature_index.is_empty() {
965 let mut buf = Vec::new();
966 encode::write_postings_to_string(&self.inverted_function_signature_index, &mut buf);
967 let mut serialized_result = Vec::new();
968 stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result);
969 seq.serialize_element(&String::from_utf8(serialized_result).unwrap())?;
970 }
971 if self.search_unbox {
972 seq.serialize_element(&1)?;
973 }
974 seq.end()
975 } else {
976 None::<()>.serialize(serializer)
977 }
978 }
979}
980
981impl<'de> Deserialize<'de> for TypeData {
982 fn deserialize<D>(deserializer: D) -> Result<TypeData, D::Error>
983 where
984 D: Deserializer<'de>,
985 {
986 struct TypeDataVisitor;
987 impl<'de> de::Visitor<'de> for TypeDataVisitor {
988 type Value = TypeData;
989 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
990 write!(formatter, "type data")
991 }
992 fn visit_none<E>(self) -> Result<TypeData, E> {
993 Ok(TypeData { inverted_function_signature_index: vec![], search_unbox: false })
994 }
995 fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<TypeData, A::Error> {
996 let inverted_function_signature_index: String =
997 v.next_element()?.unwrap_or(String::new());
998 let search_unbox: u32 = v.next_element()?.unwrap_or(0);
999 let mut idx: Vec<u8> = Vec::new();
1000 stringdex_internals::decode::read_base64_from_bytes(
1001 inverted_function_signature_index.as_bytes(),
1002 &mut idx,
1003 )
1004 .unwrap();
1005 let mut inverted_function_signature_index = Vec::new();
1006 encode::read_postings_from_string(&mut inverted_function_signature_index, &idx);
1007 Ok(TypeData { inverted_function_signature_index, search_unbox: search_unbox == 1 })
1008 }
1009 }
1010 deserializer.deserialize_any(TypeDataVisitor)
1011 }
1012}
1013
1014enum SerializedOptionalString {
1015 None,
1016 Some(String),
1017}
1018
1019impl From<SerializedOptionalString> for Option<String> {
1020 fn from(me: SerializedOptionalString) -> Option<String> {
1021 match me {
1022 SerializedOptionalString::Some(string) => Some(string),
1023 SerializedOptionalString::None => None,
1024 }
1025 }
1026}
1027
1028impl Serialize for SerializedOptionalString {
1029 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1030 where
1031 S: Serializer,
1032 {
1033 match self {
1034 SerializedOptionalString::Some(string) => string.serialize(serializer),
1035 SerializedOptionalString::None => 0.serialize(serializer),
1036 }
1037 }
1038}
1039impl<'de> Deserialize<'de> for SerializedOptionalString {
1040 fn deserialize<D>(deserializer: D) -> Result<SerializedOptionalString, D::Error>
1041 where
1042 D: Deserializer<'de>,
1043 {
1044 struct SerializedOptionalStringVisitor;
1045 impl<'de> de::Visitor<'de> for SerializedOptionalStringVisitor {
1046 type Value = SerializedOptionalString;
1047 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1048 write!(formatter, "0 or string")
1049 }
1050 fn visit_u64<E: de::Error>(self, v: u64) -> Result<SerializedOptionalString, E> {
1051 if v != 0 {
1052 return Err(E::missing_field("not 0"));
1053 }
1054 Ok(SerializedOptionalString::None)
1055 }
1056 fn visit_string<E: de::Error>(self, v: String) -> Result<SerializedOptionalString, E> {
1057 Ok(SerializedOptionalString::Some(v))
1058 }
1059 fn visit_str<E: de::Error>(self, v: &str) -> Result<SerializedOptionalString, E> {
1060 Ok(SerializedOptionalString::Some(v.to_string()))
1061 }
1062 }
1063 deserializer.deserialize_any(SerializedOptionalStringVisitor)
1064 }
1065}
1066
1067enum SerializedOptional32 {
1068 None,
1069 Some(i32),
1070}
1071
1072impl From<SerializedOptional32> for Option<i32> {
1073 fn from(me: SerializedOptional32) -> Option<i32> {
1074 match me {
1075 SerializedOptional32::Some(number) => Some(number),
1076 SerializedOptional32::None => None,
1077 }
1078 }
1079}
1080
1081impl Serialize for SerializedOptional32 {
1082 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1083 where
1084 S: Serializer,
1085 {
1086 match self {
1087 &SerializedOptional32::Some(number) if number < 0 => number.serialize(serializer),
1088 &SerializedOptional32::Some(number) => (number + 1).serialize(serializer),
1089 &SerializedOptional32::None => 0.serialize(serializer),
1090 }
1091 }
1092}
1093impl<'de> Deserialize<'de> for SerializedOptional32 {
1094 fn deserialize<D>(deserializer: D) -> Result<SerializedOptional32, D::Error>
1095 where
1096 D: Deserializer<'de>,
1097 {
1098 struct SerializedOptional32Visitor;
1099 impl<'de> de::Visitor<'de> for SerializedOptional32Visitor {
1100 type Value = SerializedOptional32;
1101 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1102 write!(formatter, "integer")
1103 }
1104 fn visit_i64<E: de::Error>(self, v: i64) -> Result<SerializedOptional32, E> {
1105 Ok(match v {
1106 0 => SerializedOptional32::None,
1107 v if v < 0 => SerializedOptional32::Some(v as i32),
1108 v => SerializedOptional32::Some(v as i32 - 1),
1109 })
1110 }
1111 fn visit_u64<E: de::Error>(self, v: u64) -> Result<SerializedOptional32, E> {
1112 Ok(match v {
1113 0 => SerializedOptional32::None,
1114 v => SerializedOptional32::Some(v as i32 - 1),
1115 })
1116 }
1117 }
1118 deserializer.deserialize_any(SerializedOptional32Visitor)
1119 }
1120}
1121
1122#[derive(Clone, Debug)]
1123pub struct FunctionData {
1124 function_signature: String,
1125 param_names: Vec<String>,
1126}
1127
1128impl Serialize for FunctionData {
1129 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1130 where
1131 S: Serializer,
1132 {
1133 let mut seq = serializer.serialize_seq(None)?;
1134 seq.serialize_element(&self.function_signature)?;
1135 seq.serialize_element(&self.param_names)?;
1136 seq.end()
1137 }
1138}
1139
1140impl<'de> Deserialize<'de> for FunctionData {
1141 fn deserialize<D>(deserializer: D) -> Result<FunctionData, D::Error>
1142 where
1143 D: Deserializer<'de>,
1144 {
1145 struct FunctionDataVisitor;
1146 impl<'de> de::Visitor<'de> for FunctionDataVisitor {
1147 type Value = FunctionData;
1148 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1149 write!(formatter, "fn data")
1150 }
1151 fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<FunctionData, A::Error> {
1152 let function_signature: String = v
1153 .next_element()?
1154 .ok_or_else(|| A::Error::missing_field("function_signature"))?;
1155 let param_names: Vec<String> =
1156 v.next_element()?.ok_or_else(|| A::Error::missing_field("param_names"))?;
1157 Ok(FunctionData { function_signature, param_names })
1158 }
1159 }
1160 deserializer.deserialize_any(FunctionDataVisitor)
1161 }
1162}
1163
1164pub(crate) fn build_index(
1166 krate: &clean::Crate,
1167 cache: &mut Cache,
1168 tcx: TyCtxt<'_>,
1169 doc_root: &Path,
1170 resource_suffix: &str,
1171) -> Result<SerializedSearchIndex, Error> {
1172 let mut search_index = std::mem::take(&mut cache.search_index);
1173
1174 for &OrphanImplItem { impl_id, parent, ref item, ref impl_generics } in &cache.orphan_impl_items
1177 {
1178 if let Some((fqp, _)) = cache.paths.get(&parent) {
1179 let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
1180 search_index.push(IndexItem {
1181 ty: item.type_(),
1182 defid: item.item_id.as_def_id(),
1183 name: item.name.unwrap(),
1184 module_path: fqp[..fqp.len() - 1].to_vec(),
1185 desc,
1186 parent: Some(parent),
1187 parent_idx: None,
1188 exact_module_path: None,
1189 impl_id,
1190 search_type: get_function_type_for_search(
1191 item,
1192 tcx,
1193 impl_generics.as_ref(),
1194 Some(parent),
1195 cache,
1196 ),
1197 aliases: item.attrs.get_doc_aliases(),
1198 deprecation: item.deprecation(tcx),
1199 is_unstable: item.stability(tcx).is_some_and(|x| x.is_unstable()),
1200 });
1201 }
1202 }
1203
1204 search_index.sort_unstable_by(|k1, k2| {
1206 let k1 =
1209 (&k1.module_path, k1.name.as_str(), &k1.ty, k1.parent.map(|id| (id.index, id.krate)));
1210 let k2 =
1211 (&k2.module_path, k2.name.as_str(), &k2.ty, k2.parent.map(|id| (id.index, id.krate)));
1212 Ord::cmp(&k1, &k2)
1213 });
1214
1215 let mut serialized_index = SerializedSearchIndex::load(doc_root, resource_suffix)?;
1220
1221 let crate_name = krate.name(tcx);
1223 let crate_doc =
1224 short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
1225 let crate_idx = {
1226 let crate_path = (ItemType::ExternCrate, vec![crate_name]);
1227 match serialized_index.crate_paths_index.entry(crate_path) {
1228 Entry::Occupied(index) => {
1229 let index = *index.get();
1230 serialized_index.descs[index] = crate_doc;
1231 for type_data in serialized_index.type_data.iter_mut() {
1232 if let Some(TypeData { inverted_function_signature_index, .. }) = type_data {
1233 for list in &mut inverted_function_signature_index[..] {
1234 list.retain(|fnid| {
1235 serialized_index.entry_data[usize::try_from(*fnid).unwrap()]
1236 .as_ref()
1237 .unwrap()
1238 .krate
1239 != index
1240 });
1241 }
1242 }
1243 }
1244 for i in (index + 1)..serialized_index.entry_data.len() {
1245 if let Some(EntryData { krate, .. }) = serialized_index.entry_data[i]
1247 && krate == index
1248 {
1249 serialized_index.entry_data[i] = None;
1250 serialized_index.descs[i] = String::new();
1251 serialized_index.function_data[i] = None;
1252 if serialized_index.path_data[i].is_none() {
1253 serialized_index.names[i] = String::new();
1254 }
1255 }
1256 if let Some(alias_pointer) = serialized_index.alias_pointers[i]
1257 && serialized_index.entry_data[alias_pointer].is_none()
1258 {
1259 serialized_index.alias_pointers[i] = None;
1260 if serialized_index.path_data[i].is_none()
1261 && serialized_index.entry_data[i].is_none()
1262 {
1263 serialized_index.names[i] = String::new();
1264 }
1265 }
1266 }
1267 index
1268 }
1269 Entry::Vacant(slot) => {
1270 let krate = serialized_index.names.len();
1271 slot.insert(krate);
1272 serialized_index.push(
1273 crate_name.as_str().to_string(),
1274 Some(PathData {
1275 ty: ItemType::ExternCrate,
1276 module_path: vec![],
1277 exact_module_path: None,
1278 }),
1279 Some(EntryData {
1280 krate,
1281 ty: ItemType::ExternCrate,
1282 module_path: None,
1283 exact_module_path: None,
1284 parent: None,
1285 deprecated: false,
1286 is_unstable: false,
1287 associated_item_disambiguator: None,
1288 }),
1289 crate_doc,
1290 None,
1291 None,
1292 None,
1293 );
1294 krate
1295 }
1296 }
1297 };
1298
1299 let crate_items: Vec<&mut IndexItem> = search_index
1301 .iter_mut()
1302 .map(|item| {
1303 item.parent_idx = item.parent.and_then(|defid| {
1304 cache.paths.get(&defid).map(|&(ref fqp, ty)| {
1305 let pathid = serialized_index.names.len();
1306 match serialized_index.crate_paths_index.entry((ty, fqp.clone())) {
1307 Entry::Occupied(entry) => *entry.get(),
1308 Entry::Vacant(entry) => {
1309 entry.insert(pathid);
1310 let (name, path) = fqp.split_last().unwrap();
1311 serialized_index.push_path(
1312 name.as_str().to_string(),
1313 PathData {
1314 ty,
1315 module_path: path.to_vec(),
1316 exact_module_path: if let Some(exact_path) =
1317 cache.exact_paths.get(&defid)
1318 && let Some((name2, exact_path)) = exact_path.split_last()
1319 && name == name2
1320 {
1321 Some(exact_path.to_vec())
1322 } else {
1323 None
1324 },
1325 },
1326 );
1327 usize::try_from(pathid).unwrap()
1328 }
1329 }
1330 })
1331 });
1332
1333 if let Some(defid) = item.defid
1334 && item.parent_idx.is_none()
1335 {
1336 let exact_fqp = cache
1340 .exact_paths
1341 .get(&defid)
1342 .or_else(|| cache.external_paths.get(&defid).map(|(fqp, _)| fqp));
1343 item.exact_module_path = exact_fqp.and_then(|fqp| {
1344 if fqp.last() != Some(&item.name) {
1351 return None;
1352 }
1353 let path =
1354 if item.ty == ItemType::Macro && tcx.has_attr(defid, sym::macro_export) {
1355 vec![tcx.crate_name(defid.krate)]
1357 } else {
1358 if fqp.len() < 2 {
1359 return None;
1360 }
1361 fqp[..fqp.len() - 1].to_vec()
1362 };
1363 if path == item.module_path {
1364 return None;
1365 }
1366 Some(path)
1367 });
1368 } else if let Some(parent_idx) = item.parent_idx {
1369 let i = usize::try_from(parent_idx).unwrap();
1370 item.module_path =
1371 serialized_index.path_data[i].as_ref().unwrap().module_path.clone();
1372 item.exact_module_path =
1373 serialized_index.path_data[i].as_ref().unwrap().exact_module_path.clone();
1374 }
1375
1376 &mut *item
1377 })
1378 .collect();
1379
1380 let mut associated_item_duplicates = FxHashMap::<(usize, ItemType, Symbol), usize>::default();
1383 for item in crate_items.iter().map(|x| &*x) {
1384 if item.impl_id.is_some()
1385 && let Some(parent_idx) = item.parent_idx
1386 {
1387 let count =
1388 associated_item_duplicates.entry((parent_idx, item.ty, item.name)).or_insert(0);
1389 *count += 1;
1390 }
1391 }
1392
1393 for item in crate_items {
1395 assert_eq!(
1396 item.parent.is_some(),
1397 item.parent_idx.is_some(),
1398 "`{}` is missing idx",
1399 item.name
1400 );
1401
1402 let module_path = Some(serialized_index.get_id_by_module_path(&item.module_path));
1403 let exact_module_path = item
1404 .exact_module_path
1405 .as_ref()
1406 .map(|path| serialized_index.get_id_by_module_path(path));
1407
1408 let new_entry_id = serialized_index.push(
1409 item.name.as_str().to_string(),
1410 None,
1411 Some(EntryData {
1412 ty: item.ty,
1413 parent: item.parent_idx,
1414 module_path,
1415 exact_module_path,
1416 deprecated: item.deprecation.is_some(),
1417 is_unstable: item.is_unstable,
1418 associated_item_disambiguator: if let Some(impl_id) = item.impl_id
1419 && let Some(parent_idx) = item.parent_idx
1420 && associated_item_duplicates
1421 .get(&(parent_idx, item.ty, item.name))
1422 .copied()
1423 .unwrap_or(0)
1424 > 1
1425 {
1426 Some(render::get_id_for_impl(tcx, ItemId::DefId(impl_id)))
1427 } else {
1428 None
1429 },
1430 krate: crate_idx,
1431 }),
1432 item.desc.to_string(),
1433 None, None,
1435 None,
1436 );
1437
1438 for alias in &item.aliases[..] {
1441 serialized_index.push_alias(alias.as_str().to_string(), new_entry_id);
1442 }
1443
1444 fn insert_into_map(
1447 ty: ItemType,
1448 path: &[Symbol],
1449 exact_path: Option<&[Symbol]>,
1450 search_unbox: bool,
1451 serialized_index: &mut SerializedSearchIndex,
1452 used_in_function_signature: &mut BTreeSet<isize>,
1453 ) -> RenderTypeId {
1454 let pathid = serialized_index.names.len();
1455 let pathid = match serialized_index.crate_paths_index.entry((ty, path.to_vec())) {
1456 Entry::Occupied(entry) => {
1457 let id = *entry.get();
1458 if serialized_index.type_data[id].as_mut().is_none() {
1459 serialized_index.type_data[id] = Some(TypeData {
1460 search_unbox,
1461 inverted_function_signature_index: Vec::new(),
1462 });
1463 } else if search_unbox {
1464 serialized_index.type_data[id].as_mut().unwrap().search_unbox = true;
1465 }
1466 id
1467 }
1468 Entry::Vacant(entry) => {
1469 entry.insert(pathid);
1470 let (name, path) = path.split_last().unwrap();
1471 serialized_index.push_type(
1472 name.to_string(),
1473 PathData {
1474 ty,
1475 module_path: path.to_vec(),
1476 exact_module_path: if let Some(exact_path) = exact_path
1477 && let Some((name2, exact_path)) = exact_path.split_last()
1478 && name == name2
1479 {
1480 Some(exact_path.to_vec())
1481 } else {
1482 None
1483 },
1484 },
1485 TypeData { search_unbox, inverted_function_signature_index: Vec::new() },
1486 );
1487 pathid
1488 }
1489 };
1490 used_in_function_signature.insert(isize::try_from(pathid).unwrap());
1491 RenderTypeId::Index(isize::try_from(pathid).unwrap())
1492 }
1493
1494 fn convert_render_type_id(
1495 id: RenderTypeId,
1496 cache: &mut Cache,
1497 serialized_index: &mut SerializedSearchIndex,
1498 used_in_function_signature: &mut BTreeSet<isize>,
1499 tcx: TyCtxt<'_>,
1500 ) -> Option<RenderTypeId> {
1501 use crate::clean::PrimitiveType;
1502 let Cache { ref paths, ref external_paths, ref exact_paths, .. } = *cache;
1503 let search_unbox = match id {
1504 RenderTypeId::Mut => false,
1505 RenderTypeId::DefId(defid) => utils::has_doc_flag(tcx, defid, sym::search_unbox),
1506 RenderTypeId::Primitive(PrimitiveType::Reference | PrimitiveType::Tuple) => true,
1507 RenderTypeId::Primitive(..) => false,
1508 RenderTypeId::AssociatedType(..) => false,
1509 RenderTypeId::Index(_) => false,
1512 };
1513 match id {
1514 RenderTypeId::Mut => Some(insert_into_map(
1515 ItemType::Keyword,
1516 &[kw::Mut],
1517 None,
1518 search_unbox,
1519 serialized_index,
1520 used_in_function_signature,
1521 )),
1522 RenderTypeId::DefId(defid) => {
1523 if let Some(&(ref fqp, item_type)) =
1524 paths.get(&defid).or_else(|| external_paths.get(&defid))
1525 {
1526 if tcx.lang_items().fn_mut_trait() == Some(defid)
1527 || tcx.lang_items().fn_once_trait() == Some(defid)
1528 || tcx.lang_items().fn_trait() == Some(defid)
1529 {
1530 let name = *fqp.last().unwrap();
1531 Some(insert_into_map(
1536 item_type,
1537 &[sym::core, sym::ops, name],
1538 Some(&[sym::core, sym::ops, name]),
1539 search_unbox,
1540 serialized_index,
1541 used_in_function_signature,
1542 ))
1543 } else {
1544 let exact_fqp = exact_paths
1545 .get(&defid)
1546 .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp))
1547 .map(|v| &v[..])
1548 .filter(|this_fqp| this_fqp.last() == fqp.last());
1555 Some(insert_into_map(
1556 item_type,
1557 fqp,
1558 exact_fqp,
1559 search_unbox,
1560 serialized_index,
1561 used_in_function_signature,
1562 ))
1563 }
1564 } else {
1565 None
1566 }
1567 }
1568 RenderTypeId::Primitive(primitive) => {
1569 let sym = primitive.as_sym();
1570 Some(insert_into_map(
1571 ItemType::Primitive,
1572 &[sym],
1573 None,
1574 search_unbox,
1575 serialized_index,
1576 used_in_function_signature,
1577 ))
1578 }
1579 RenderTypeId::Index(index) => {
1580 used_in_function_signature.insert(index);
1581 Some(id)
1582 }
1583 RenderTypeId::AssociatedType(sym) => Some(insert_into_map(
1584 ItemType::AssocType,
1585 &[sym],
1586 None,
1587 search_unbox,
1588 serialized_index,
1589 used_in_function_signature,
1590 )),
1591 }
1592 }
1593
1594 fn convert_render_type(
1595 ty: &mut RenderType,
1596 cache: &mut Cache,
1597 serialized_index: &mut SerializedSearchIndex,
1598 used_in_function_signature: &mut BTreeSet<isize>,
1599 tcx: TyCtxt<'_>,
1600 ) {
1601 if let Some(generics) = &mut ty.generics {
1602 for item in generics {
1603 convert_render_type(
1604 item,
1605 cache,
1606 serialized_index,
1607 used_in_function_signature,
1608 tcx,
1609 );
1610 }
1611 }
1612 if let Some(bindings) = &mut ty.bindings {
1613 bindings.retain_mut(|(associated_type, constraints)| {
1614 let converted_associated_type = convert_render_type_id(
1615 *associated_type,
1616 cache,
1617 serialized_index,
1618 used_in_function_signature,
1619 tcx,
1620 );
1621 let Some(converted_associated_type) = converted_associated_type else {
1622 return false;
1623 };
1624 *associated_type = converted_associated_type;
1625 for constraint in constraints {
1626 convert_render_type(
1627 constraint,
1628 cache,
1629 serialized_index,
1630 used_in_function_signature,
1631 tcx,
1632 );
1633 }
1634 true
1635 });
1636 }
1637 let Some(id) = ty.id else {
1638 assert!(ty.generics.is_some());
1639 return;
1640 };
1641 ty.id = convert_render_type_id(
1642 id,
1643 cache,
1644 serialized_index,
1645 used_in_function_signature,
1646 tcx,
1647 );
1648 use crate::clean::PrimitiveType;
1649 match id {
1653 RenderTypeId::Primitive(PrimitiveType::Array | PrimitiveType::Slice) => {
1655 insert_into_map(
1656 ItemType::Primitive,
1657 &[Symbol::intern("[]")],
1658 None,
1659 false,
1660 serialized_index,
1661 used_in_function_signature,
1662 );
1663 }
1664 RenderTypeId::Primitive(PrimitiveType::Tuple | PrimitiveType::Unit) => {
1665 insert_into_map(
1667 ItemType::Primitive,
1668 &[Symbol::intern("()")],
1669 None,
1670 false,
1671 serialized_index,
1672 used_in_function_signature,
1673 );
1674 }
1675 RenderTypeId::Primitive(PrimitiveType::Fn) => {
1677 insert_into_map(
1678 ItemType::Primitive,
1679 &[Symbol::intern("->")],
1680 None,
1681 false,
1682 serialized_index,
1683 used_in_function_signature,
1684 );
1685 }
1686 RenderTypeId::DefId(did)
1687 if tcx.lang_items().fn_mut_trait() == Some(did)
1688 || tcx.lang_items().fn_once_trait() == Some(did)
1689 || tcx.lang_items().fn_trait() == Some(did) =>
1690 {
1691 insert_into_map(
1692 ItemType::Primitive,
1693 &[Symbol::intern("->")],
1694 None,
1695 false,
1696 serialized_index,
1697 used_in_function_signature,
1698 );
1699 }
1700 _ => {}
1702 }
1703 }
1704 if let Some(search_type) = &mut item.search_type {
1705 let mut used_in_function_signature = BTreeSet::new();
1706 for item in &mut search_type.inputs {
1707 convert_render_type(
1708 item,
1709 cache,
1710 &mut serialized_index,
1711 &mut used_in_function_signature,
1712 tcx,
1713 );
1714 }
1715 for item in &mut search_type.output {
1716 convert_render_type(
1717 item,
1718 cache,
1719 &mut serialized_index,
1720 &mut used_in_function_signature,
1721 tcx,
1722 );
1723 }
1724 for constraint in &mut search_type.where_clause {
1725 for trait_ in &mut constraint[..] {
1726 convert_render_type(
1727 trait_,
1728 cache,
1729 &mut serialized_index,
1730 &mut used_in_function_signature,
1731 tcx,
1732 );
1733 }
1734 }
1735 let search_type_size = search_type.size() +
1736 if item.ty.is_fn_like() { 0 } else { 16 };
1744 serialized_index.function_data[new_entry_id] = Some(FunctionData {
1745 function_signature: {
1746 let mut function_signature = String::new();
1747 search_type.write_to_string_without_param_names(&mut function_signature);
1748 function_signature
1749 },
1750 param_names: search_type
1751 .param_names
1752 .iter()
1753 .map(|sym| sym.map(|sym| sym.to_string()).unwrap_or(String::new()))
1754 .collect::<Vec<String>>(),
1755 });
1756 for index in used_in_function_signature {
1757 let postings = if index >= 0 {
1758 assert!(serialized_index.path_data[index as usize].is_some());
1759 &mut serialized_index.type_data[index as usize]
1760 .as_mut()
1761 .unwrap()
1762 .inverted_function_signature_index
1763 } else {
1764 let generic_id = usize::try_from(-index).unwrap() - 1;
1765 for _ in serialized_index.generic_inverted_index.len()..=generic_id {
1766 serialized_index.generic_inverted_index.push(Vec::new());
1767 }
1768 &mut serialized_index.generic_inverted_index[generic_id]
1769 };
1770 while postings.len() <= search_type_size {
1771 postings.push(Vec::new());
1772 }
1773 postings[search_type_size].push(new_entry_id as u32);
1774 }
1775 }
1776 }
1777
1778 Ok(serialized_index.sort())
1779}
1780
1781pub(crate) fn get_function_type_for_search(
1782 item: &clean::Item,
1783 tcx: TyCtxt<'_>,
1784 impl_generics: Option<&(clean::Type, clean::Generics)>,
1785 parent: Option<DefId>,
1786 cache: &Cache,
1787) -> Option<IndexItemFunctionType> {
1788 let mut trait_info = None;
1789 let impl_or_trait_generics = impl_generics.or_else(|| {
1790 if let Some(def_id) = parent
1791 && let Some(trait_) = cache.traits.get(&def_id)
1792 && let Some((path, _)) =
1793 cache.paths.get(&def_id).or_else(|| cache.external_paths.get(&def_id))
1794 {
1795 let path = clean::Path {
1796 res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, def_id),
1797 segments: path
1798 .iter()
1799 .map(|name| clean::PathSegment {
1800 name: *name,
1801 args: clean::GenericArgs::AngleBracketed {
1802 args: ThinVec::new(),
1803 constraints: ThinVec::new(),
1804 },
1805 })
1806 .collect(),
1807 };
1808 trait_info = Some((clean::Type::Path { path }, trait_.generics.clone()));
1809 Some(trait_info.as_ref().unwrap())
1810 } else {
1811 None
1812 }
1813 });
1814 let (mut inputs, mut output, param_names, where_clause) = match item.kind {
1815 clean::ForeignFunctionItem(ref f, _)
1816 | clean::FunctionItem(ref f)
1817 | clean::MethodItem(ref f, _)
1818 | clean::RequiredMethodItem(ref f) => {
1819 get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
1820 }
1821 clean::ConstantItem(ref c) => make_nullary_fn(&c.type_),
1822 clean::StaticItem(ref s) => make_nullary_fn(&s.type_),
1823 clean::StructFieldItem(ref t) if let Some(parent) = parent => {
1824 let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> =
1825 Default::default();
1826 let output = get_index_type(t, vec![], &mut rgen);
1827 let input = RenderType {
1828 id: Some(RenderTypeId::DefId(parent)),
1829 generics: None,
1830 bindings: None,
1831 };
1832 (vec![input], vec![output], vec![], vec![])
1833 }
1834 _ => return None,
1835 };
1836
1837 inputs.retain(|a| a.id.is_some() || a.generics.is_some());
1838 output.retain(|a| a.id.is_some() || a.generics.is_some());
1839
1840 Some(IndexItemFunctionType { inputs, output, where_clause, param_names })
1841}
1842
1843fn get_index_type(
1844 clean_type: &clean::Type,
1845 generics: Vec<RenderType>,
1846 rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
1847) -> RenderType {
1848 RenderType {
1849 id: get_index_type_id(clean_type, rgen),
1850 generics: if generics.is_empty() { None } else { Some(generics) },
1851 bindings: None,
1852 }
1853}
1854
1855fn get_index_type_id(
1856 clean_type: &clean::Type,
1857 rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
1858) -> Option<RenderTypeId> {
1859 use rustc_hir::def::{DefKind, Res};
1860 match *clean_type {
1861 clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())),
1862 clean::DynTrait(ref bounds, _) => {
1863 bounds.first().map(|b| RenderTypeId::DefId(b.trait_.def_id()))
1864 }
1865 clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
1866 clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)),
1867 clean::RawPointer(_, ref type_) => get_index_type_id(type_, rgen),
1868 clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)),
1870 clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)),
1871 clean::BareFunction(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Fn)),
1872 clean::Tuple(ref n) if n.is_empty() => {
1873 Some(RenderTypeId::Primitive(clean::PrimitiveType::Unit))
1874 }
1875 clean::Tuple(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Tuple)),
1876 clean::QPath(ref data) => {
1877 if data.self_type.is_self_type()
1878 && let Some(clean::Path { res: Res::Def(DefKind::Trait, trait_), .. }) = data.trait_
1879 {
1880 let idx = -isize::try_from(rgen.len() + 1).unwrap();
1881 let (idx, _) = rgen
1882 .entry(SimplifiedParam::AssociatedType(trait_, data.assoc.name))
1883 .or_insert_with(|| (idx, Vec::new()));
1884 Some(RenderTypeId::Index(*idx))
1885 } else {
1886 None
1887 }
1888 }
1889 clean::Type::Pat(..)
1891 | clean::Generic(_)
1892 | clean::SelfTy
1893 | clean::ImplTrait(_)
1894 | clean::Infer
1895 | clean::UnsafeBinder(_) => None,
1896 }
1897}
1898
1899#[derive(Clone, Copy, Eq, Hash, PartialEq)]
1900enum SimplifiedParam {
1901 Symbol(Symbol),
1903 Anonymous(isize),
1905 AssociatedType(DefId, Symbol),
1908}
1909
1910#[instrument(level = "trace", skip(tcx, res, rgen, cache))]
1920fn simplify_fn_type<'a, 'tcx>(
1921 self_: Option<&'a Type>,
1922 generics: &Generics,
1923 arg: &'a Type,
1924 tcx: TyCtxt<'tcx>,
1925 recurse: usize,
1926 res: &mut Vec<RenderType>,
1927 rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
1928 is_return: bool,
1929 cache: &Cache,
1930) {
1931 if recurse >= 10 {
1932 return;
1935 }
1936
1937 let (is_self, arg) = if let Some(self_) = self_
1939 && arg.is_self_type()
1940 {
1941 (true, self_)
1942 } else {
1943 (false, arg)
1944 };
1945
1946 match *arg {
1949 Type::Generic(arg_s) => {
1950 let mut type_bounds = Vec::new();
1952 for where_pred in generics.where_predicates.iter().filter(|g| match g {
1953 WherePredicate::BoundPredicate { ty, .. } => *ty == *arg,
1954 _ => false,
1955 }) {
1956 let bounds = where_pred.get_bounds().unwrap_or(&[]);
1957 for bound in bounds.iter() {
1958 if let Some(path) = bound.get_trait_path() {
1959 let ty = Type::Path { path };
1960 simplify_fn_type(
1961 self_,
1962 generics,
1963 &ty,
1964 tcx,
1965 recurse + 1,
1966 &mut type_bounds,
1967 rgen,
1968 is_return,
1969 cache,
1970 );
1971 }
1972 }
1973 }
1974 if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
1976 for bound in bound.get_bounds().unwrap_or(&[]) {
1977 if let Some(path) = bound.get_trait_path() {
1978 let ty = Type::Path { path };
1979 simplify_fn_type(
1980 self_,
1981 generics,
1982 &ty,
1983 tcx,
1984 recurse + 1,
1985 &mut type_bounds,
1986 rgen,
1987 is_return,
1988 cache,
1989 );
1990 }
1991 }
1992 }
1993 if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
1994 res.push(RenderType {
1995 id: Some(RenderTypeId::Index(*idx)),
1996 generics: None,
1997 bindings: None,
1998 });
1999 } else {
2000 let idx = -isize::try_from(rgen.len() + 1).unwrap();
2001 rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
2002 res.push(RenderType {
2003 id: Some(RenderTypeId::Index(idx)),
2004 generics: None,
2005 bindings: None,
2006 });
2007 }
2008 }
2009 Type::ImplTrait(ref bounds) => {
2010 let mut type_bounds = Vec::new();
2011 for bound in bounds {
2012 if let Some(path) = bound.get_trait_path() {
2013 let ty = Type::Path { path };
2014 simplify_fn_type(
2015 self_,
2016 generics,
2017 &ty,
2018 tcx,
2019 recurse + 1,
2020 &mut type_bounds,
2021 rgen,
2022 is_return,
2023 cache,
2024 );
2025 }
2026 }
2027 if is_return && !type_bounds.is_empty() {
2028 res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None });
2030 } else {
2031 let idx = -isize::try_from(rgen.len() + 1).unwrap();
2033 rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
2034 res.push(RenderType {
2035 id: Some(RenderTypeId::Index(idx)),
2036 generics: None,
2037 bindings: None,
2038 });
2039 }
2040 }
2041 Type::Slice(ref ty) => {
2042 let mut ty_generics = Vec::new();
2043 simplify_fn_type(
2044 self_,
2045 generics,
2046 ty,
2047 tcx,
2048 recurse + 1,
2049 &mut ty_generics,
2050 rgen,
2051 is_return,
2052 cache,
2053 );
2054 res.push(get_index_type(arg, ty_generics, rgen));
2055 }
2056 Type::Array(ref ty, _) => {
2057 let mut ty_generics = Vec::new();
2058 simplify_fn_type(
2059 self_,
2060 generics,
2061 ty,
2062 tcx,
2063 recurse + 1,
2064 &mut ty_generics,
2065 rgen,
2066 is_return,
2067 cache,
2068 );
2069 res.push(get_index_type(arg, ty_generics, rgen));
2070 }
2071 Type::Tuple(ref tys) => {
2072 let mut ty_generics = Vec::new();
2073 for ty in tys {
2074 simplify_fn_type(
2075 self_,
2076 generics,
2077 ty,
2078 tcx,
2079 recurse + 1,
2080 &mut ty_generics,
2081 rgen,
2082 is_return,
2083 cache,
2084 );
2085 }
2086 res.push(get_index_type(arg, ty_generics, rgen));
2087 }
2088 Type::BareFunction(ref bf) => {
2089 let mut ty_generics = Vec::new();
2090 for ty in bf.decl.inputs.iter().map(|arg| &arg.type_) {
2091 simplify_fn_type(
2092 self_,
2093 generics,
2094 ty,
2095 tcx,
2096 recurse + 1,
2097 &mut ty_generics,
2098 rgen,
2099 is_return,
2100 cache,
2101 );
2102 }
2103 let mut ty_output = Vec::new();
2107 simplify_fn_type(
2108 self_,
2109 generics,
2110 &bf.decl.output,
2111 tcx,
2112 recurse + 1,
2113 &mut ty_output,
2114 rgen,
2115 is_return,
2116 cache,
2117 );
2118 let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
2119 res.push(RenderType {
2120 id: get_index_type_id(arg, rgen),
2121 bindings: Some(ty_bindings),
2122 generics: Some(ty_generics),
2123 });
2124 }
2125 Type::BorrowedRef { lifetime: _, mutability, ref type_ } => {
2126 let mut ty_generics = Vec::new();
2127 if mutability.is_mut() {
2128 ty_generics.push(RenderType {
2129 id: Some(RenderTypeId::Mut),
2130 generics: None,
2131 bindings: None,
2132 });
2133 }
2134 simplify_fn_type(
2135 self_,
2136 generics,
2137 type_,
2138 tcx,
2139 recurse + 1,
2140 &mut ty_generics,
2141 rgen,
2142 is_return,
2143 cache,
2144 );
2145 res.push(get_index_type(arg, ty_generics, rgen));
2146 }
2147 _ => {
2148 let mut ty_generics = Vec::new();
2154 let mut ty_constraints = Vec::new();
2155 if let Some(arg_generics) = arg.generic_args() {
2156 for ty in arg_generics.into_iter().filter_map(|param| match param {
2157 clean::GenericArg::Type(ty) => Some(ty),
2158 _ => None,
2159 }) {
2160 simplify_fn_type(
2161 self_,
2162 generics,
2163 &ty,
2164 tcx,
2165 recurse + 1,
2166 &mut ty_generics,
2167 rgen,
2168 is_return,
2169 cache,
2170 );
2171 }
2172 for constraint in arg_generics.constraints() {
2173 simplify_fn_constraint(
2174 self_,
2175 generics,
2176 &constraint,
2177 tcx,
2178 recurse + 1,
2179 &mut ty_constraints,
2180 rgen,
2181 is_return,
2182 cache,
2183 );
2184 }
2185 }
2186 if is_self
2199 && let Type::Path { path } = arg
2200 && let def_id = path.def_id()
2201 && let Some(trait_) = cache.traits.get(&def_id)
2202 && trait_.items.iter().any(|at| at.is_required_associated_type())
2203 {
2204 for assoc_ty in &trait_.items {
2205 if let clean::ItemKind::RequiredAssocTypeItem(_generics, bounds) =
2206 &assoc_ty.kind
2207 && let Some(name) = assoc_ty.name
2208 {
2209 let idx = -isize::try_from(rgen.len() + 1).unwrap();
2210 let (idx, stored_bounds) = rgen
2211 .entry(SimplifiedParam::AssociatedType(def_id, name))
2212 .or_insert_with(|| (idx, Vec::new()));
2213 let idx = *idx;
2214 if stored_bounds.is_empty() {
2215 let mut type_bounds = Vec::new();
2219 for bound in bounds {
2220 if let Some(path) = bound.get_trait_path() {
2221 let ty = Type::Path { path };
2222 simplify_fn_type(
2223 self_,
2224 generics,
2225 &ty,
2226 tcx,
2227 recurse + 1,
2228 &mut type_bounds,
2229 rgen,
2230 is_return,
2231 cache,
2232 );
2233 }
2234 }
2235 let stored_bounds = &mut rgen
2236 .get_mut(&SimplifiedParam::AssociatedType(def_id, name))
2237 .unwrap()
2238 .1;
2239 if stored_bounds.is_empty() {
2240 *stored_bounds = type_bounds;
2241 }
2242 }
2243 ty_constraints.push((
2244 RenderTypeId::AssociatedType(name),
2245 vec![RenderType {
2246 id: Some(RenderTypeId::Index(idx)),
2247 generics: None,
2248 bindings: None,
2249 }],
2250 ))
2251 }
2252 }
2253 }
2254 let id = get_index_type_id(arg, rgen);
2255 if id.is_some() || !ty_generics.is_empty() {
2256 res.push(RenderType {
2257 id,
2258 bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
2259 generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
2260 });
2261 }
2262 }
2263 }
2264}
2265
2266fn simplify_fn_constraint<'a>(
2267 self_: Option<&'a Type>,
2268 generics: &Generics,
2269 constraint: &'a clean::AssocItemConstraint,
2270 tcx: TyCtxt<'_>,
2271 recurse: usize,
2272 res: &mut Vec<(RenderTypeId, Vec<RenderType>)>,
2273 rgen: &mut FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)>,
2274 is_return: bool,
2275 cache: &Cache,
2276) {
2277 let mut ty_constraints = Vec::new();
2278 let ty_constrained_assoc = RenderTypeId::AssociatedType(constraint.assoc.name);
2279 for param in &constraint.assoc.args {
2280 match param {
2281 clean::GenericArg::Type(arg) => simplify_fn_type(
2282 self_,
2283 generics,
2284 &arg,
2285 tcx,
2286 recurse + 1,
2287 &mut ty_constraints,
2288 rgen,
2289 is_return,
2290 cache,
2291 ),
2292 clean::GenericArg::Lifetime(_)
2293 | clean::GenericArg::Const(_)
2294 | clean::GenericArg::Infer => {}
2295 }
2296 }
2297 for constraint in constraint.assoc.args.constraints() {
2298 simplify_fn_constraint(
2299 self_,
2300 generics,
2301 &constraint,
2302 tcx,
2303 recurse + 1,
2304 res,
2305 rgen,
2306 is_return,
2307 cache,
2308 );
2309 }
2310 match &constraint.kind {
2311 clean::AssocItemConstraintKind::Equality { term } => {
2312 if let clean::Term::Type(arg) = &term {
2313 simplify_fn_type(
2314 self_,
2315 generics,
2316 arg,
2317 tcx,
2318 recurse + 1,
2319 &mut ty_constraints,
2320 rgen,
2321 is_return,
2322 cache,
2323 );
2324 }
2325 }
2326 clean::AssocItemConstraintKind::Bound { bounds } => {
2327 for bound in &bounds[..] {
2328 if let Some(path) = bound.get_trait_path() {
2329 let ty = Type::Path { path };
2330 simplify_fn_type(
2331 self_,
2332 generics,
2333 &ty,
2334 tcx,
2335 recurse + 1,
2336 &mut ty_constraints,
2337 rgen,
2338 is_return,
2339 cache,
2340 );
2341 }
2342 }
2343 }
2344 }
2345 res.push((ty_constrained_assoc, ty_constraints));
2346}
2347
2348fn make_nullary_fn(
2352 clean_type: &clean::Type,
2353) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
2354 let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
2355 let output = get_index_type(clean_type, vec![], &mut rgen);
2356 (vec![], vec![output], vec![], vec![])
2357}
2358
2359fn get_fn_inputs_and_outputs(
2364 func: &Function,
2365 tcx: TyCtxt<'_>,
2366 impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>,
2367 cache: &Cache,
2368) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
2369 let decl = &func.decl;
2370
2371 let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
2372
2373 let combined_generics;
2374 let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_or_trait_generics {
2375 match (impl_generics.is_empty(), func.generics.is_empty()) {
2376 (true, _) => (Some(impl_self), &func.generics),
2377 (_, true) => (Some(impl_self), impl_generics),
2378 (false, false) => {
2379 let params =
2380 func.generics.params.iter().chain(&impl_generics.params).cloned().collect();
2381 let where_predicates = func
2382 .generics
2383 .where_predicates
2384 .iter()
2385 .chain(&impl_generics.where_predicates)
2386 .cloned()
2387 .collect();
2388 combined_generics = clean::Generics { params, where_predicates };
2389 (Some(impl_self), &combined_generics)
2390 }
2391 }
2392 } else {
2393 (None, &func.generics)
2394 };
2395
2396 let mut param_types = Vec::new();
2397 for param in decl.inputs.iter() {
2398 simplify_fn_type(
2399 self_,
2400 generics,
2401 ¶m.type_,
2402 tcx,
2403 0,
2404 &mut param_types,
2405 &mut rgen,
2406 false,
2407 cache,
2408 );
2409 }
2410
2411 let mut ret_types = Vec::new();
2412 simplify_fn_type(self_, generics, &decl.output, tcx, 0, &mut ret_types, &mut rgen, true, cache);
2413
2414 let mut simplified_params = rgen.into_iter().collect::<Vec<_>>();
2415 simplified_params.sort_by_key(|(_, (idx, _))| -idx);
2416 (
2417 param_types,
2418 ret_types,
2419 simplified_params
2420 .iter()
2421 .map(|(name, (_idx, _traits))| match name {
2422 SimplifiedParam::Symbol(name) => Some(*name),
2423 SimplifiedParam::Anonymous(_) => None,
2424 SimplifiedParam::AssociatedType(def_id, name) => {
2425 Some(Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name)))
2426 }
2427 })
2428 .collect(),
2429 simplified_params.into_iter().map(|(_name, (_idx, traits))| traits).collect(),
2430 )
2431}