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