From 190616e100767f45372d74c50e4f19027eb5af80 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 8 Nov 2025 12:35:03 +0200 Subject: [PATCH 1/6] `map_fn_sig_item` doesn't need a mutable reference --- src/librustdoc/html/render/search_index.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 3514c517d9134..33a86a54636a6 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -458,7 +458,7 @@ impl SerializedSearchIndex { other.descs[other_entryid].clone(), other.function_data[other_entryid].clone().map(|mut func| { fn map_fn_sig_item( - map_other_pathid_to_self_pathid: &mut Vec, + map_other_pathid_to_self_pathid: &Vec, ty: &mut RenderType, ) { match ty.id { @@ -501,14 +501,14 @@ impl SerializedSearchIndex { } } for input in &mut func.inputs { - map_fn_sig_item(&mut map_other_pathid_to_self_pathid, input); + map_fn_sig_item(&map_other_pathid_to_self_pathid, input); } for output in &mut func.output { - map_fn_sig_item(&mut map_other_pathid_to_self_pathid, output); + map_fn_sig_item(&map_other_pathid_to_self_pathid, output); } for clause in &mut func.where_clause { for entry in clause { - map_fn_sig_item(&mut map_other_pathid_to_self_pathid, entry); + map_fn_sig_item(&map_other_pathid_to_self_pathid, entry); } } func From bf29cb64e1109f8df28364af53b102cd4f17ffd7 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 21 Nov 2025 23:03:59 +0200 Subject: [PATCH 2/6] Small cleanups --- .../html/render/search_index/encode.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index a05c14374d1de..92a01a085984e 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -52,6 +52,9 @@ pub fn read_signed_vlqhex_from_string(string: &[u8]) -> Option<(i32, usize)> { } pub fn write_postings_to_string(postings: &[Vec], buf: &mut Vec) { + // there's gonna be at least 1 byte pushed for every posting + buf.reserve(postings.len()); + for list in postings { if list.is_empty() { buf.push(0); @@ -63,19 +66,14 @@ pub fn write_postings_to_string(postings: &[Vec], buf: &mut Vec) { if len_after - len_before > 1 + (4 * list.len()) && list.len() < 0x3a { buf.truncate(len_before); buf.push(list.len() as u8); - for &item in list { - buf.push(item as u8); - buf.push((item >> 8) as u8); - buf.push((item >> 16) as u8); - buf.push((item >> 24) as u8); - } + buf.extend(list.iter().copied().map(u32::to_le_bytes).flatten()); } } } pub fn read_postings_from_string(postings: &mut Vec>, mut buf: &[u8]) { use stringdex::internals::decode::RoaringBitmap; - while let Some(&c) = buf.get(0) { + while let Some(&c) = buf.first() { if c < 0x3a { buf = &buf[1..]; let buf = buf.split_off(..usize::from(c) * size_of::()).unwrap(); @@ -83,9 +81,7 @@ pub fn read_postings_from_string(postings: &mut Vec>, mut buf: &[u8]) { let slot = chunks.iter().copied().map(u32::from_le_bytes).collect(); postings.push(slot); } else { - let (bitmap, consumed_bytes_len) = - RoaringBitmap::from_bytes(buf).unwrap_or_else(|| (RoaringBitmap::default(), 0)); - assert_ne!(consumed_bytes_len, 0); + let (bitmap, consumed_bytes_len) = RoaringBitmap::from_bytes(buf).unwrap(); postings.push(bitmap.to_vec()); buf = &buf[consumed_bytes_len..]; } From f70d67fcadca9d6c5e6f6ffb981fa3f66891b216 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 21 Nov 2025 23:05:22 +0200 Subject: [PATCH 3/6] Pre-ensure size of vectors when performing union, instead of `push`ing default elements one by one --- src/librustdoc/html/render/search_index.rs | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 33a86a54636a6..c70fda58513b2 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -3,9 +3,9 @@ mod serde; use std::collections::BTreeSet; use std::collections::hash_map::Entry; -use std::io; use std::path::Path; use std::string::FromUtf8Error; +use std::{io, iter}; use ::serde::de::{self, Deserializer, Error as _}; use ::serde::ser::{SerializeSeq, Serializer}; @@ -555,19 +555,19 @@ impl SerializedSearchIndex { ); } } - for (i, other_generic_inverted_index) in other.generic_inverted_index.iter().enumerate() { - for (size, other_list) in other_generic_inverted_index.iter().enumerate() { - let self_generic_inverted_index = match self.generic_inverted_index.get_mut(i) { - Some(self_generic_inverted_index) => self_generic_inverted_index, - None => { - self.generic_inverted_index.push(Vec::new()); - self.generic_inverted_index.last_mut().unwrap() - } - }; - while self_generic_inverted_index.len() <= size { - self_generic_inverted_index.push(Vec::new()); - } - self_generic_inverted_index[size].extend( + if other.generic_inverted_index.len() > self.generic_inverted_index.len() { + self.generic_inverted_index.resize(other.generic_inverted_index.len(), Vec::new()); + } + for (other_generic_inverted_index, self_generic_inverted_index) in + iter::zip(&other.generic_inverted_index, &mut self.generic_inverted_index) + { + if other_generic_inverted_index.len() > self_generic_inverted_index.len() { + self_generic_inverted_index.resize(other_generic_inverted_index.len(), Vec::new()); + } + for (other_list, self_list) in + iter::zip(other_generic_inverted_index, self_generic_inverted_index) + { + self_list.extend( other_list .iter() .copied() From 90f2073db6ea71db5d0d1c889ba587fbce78b9af Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 21 Nov 2025 23:31:09 +0200 Subject: [PATCH 4/6] Extract common functionality into closure Also, use `Vec::resize` instead of individual `push`es --- src/librustdoc/html/render/search_index.rs | 76 +++++++++++----------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index c70fda58513b2..be5437395cb01 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1864,48 +1864,50 @@ pub(crate) fn build_index( // unoccupied size. if item.ty.is_fn_like() { 0 } else { 16 }; serialized_index.function_data[new_entry_id] = Some(search_type.clone()); - for index in used_in_function_inputs { - let postings = if index >= 0 { - assert!(serialized_index.path_data[index as usize].is_some()); - &mut serialized_index.type_data[index as usize] - .as_mut() - .unwrap() - .inverted_function_inputs_index - } else { - let generic_id = usize::try_from(-index).unwrap() - 1; - for _ in serialized_index.generic_inverted_index.len()..=generic_id { - serialized_index.generic_inverted_index.push(Vec::new()); + + #[derive(Clone, Copy)] + enum InvertedIndexType { + Inputs, + Output, + } + impl InvertedIndexType { + fn from_type_data(self, type_data: &mut TypeData) -> &mut Vec> { + match self { + Self::Inputs => &mut type_data.inverted_function_inputs_index, + Self::Output => &mut type_data.inverted_function_output_index, } - &mut serialized_index.generic_inverted_index[generic_id] - }; - while postings.len() <= search_type_size { - postings.push(Vec::new()); - } - if postings[search_type_size].last() != Some(&(new_entry_id as u32)) { - postings[search_type_size].push(new_entry_id as u32); } } - for index in used_in_function_output { - let postings = if index >= 0 { - assert!(serialized_index.path_data[index as usize].is_some()); - &mut serialized_index.type_data[index as usize] - .as_mut() - .unwrap() - .inverted_function_output_index - } else { - let generic_id = usize::try_from(-index).unwrap() - 1; - for _ in serialized_index.generic_inverted_index.len()..=generic_id { - serialized_index.generic_inverted_index.push(Vec::new()); + + let mut process_used_in_function = + |used_in_function: BTreeSet, index_type: InvertedIndexType| { + for index in used_in_function { + let postings = if index >= 0 { + assert!(serialized_index.path_data[index as usize].is_some()); + index_type.from_type_data( + serialized_index.type_data[index as usize].as_mut().unwrap(), + ) + } else { + let generic_id = index.unsigned_abs() - 1; + if generic_id >= serialized_index.generic_inverted_index.len() { + serialized_index + .generic_inverted_index + .resize(generic_id + 1, Vec::new()); + } + &mut serialized_index.generic_inverted_index[generic_id] + }; + if search_type_size >= postings.len() { + postings.resize(search_type_size + 1, Vec::new()); + } + let posting = &mut postings[search_type_size]; + if posting.last() != Some(&(new_entry_id as u32)) { + posting.push(new_entry_id as u32); + } } - &mut serialized_index.generic_inverted_index[generic_id] }; - while postings.len() <= search_type_size { - postings.push(Vec::new()); - } - if postings[search_type_size].last() != Some(&(new_entry_id as u32)) { - postings[search_type_size].push(new_entry_id as u32); - } - } + + process_used_in_function(used_in_function_inputs, InvertedIndexType::Inputs); + process_used_in_function(used_in_function_output, InvertedIndexType::Output); } } From 56e0ce4360b8c44286338ec019e2dc961ce3d060 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sun, 23 Nov 2025 19:06:50 +0200 Subject: [PATCH 5/6] `collect` into vectors --- src/librustdoc/html/render/search_index.rs | 49 ++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index be5437395cb01..29f19ec6ca882 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -256,10 +256,14 @@ impl SerializedSearchIndex { /// The returned ID can be used to attach more data to the search result. fn add_entry(&mut self, name: Symbol, entry_data: EntryData, desc: String) -> usize { let fqp = if let Some(module_path_index) = entry_data.module_path { - let mut fqp = self.path_data[module_path_index].as_ref().unwrap().module_path.clone(); - fqp.push(Symbol::intern(&self.names[module_path_index])); - fqp.push(name); - fqp + self.path_data[module_path_index] + .as_ref() + .unwrap() + .module_path + .iter() + .copied() + .chain([Symbol::intern(&self.names[module_path_index]), name]) + .collect() } else { vec![name] }; @@ -306,13 +310,13 @@ impl SerializedSearchIndex { pub(crate) fn union(mut self, other: &SerializedSearchIndex) -> SerializedSearchIndex { let other_entryid_offset = self.names.len(); - let mut map_other_pathid_to_self_pathid: Vec = Vec::new(); + let mut map_other_pathid_to_self_pathid = Vec::with_capacity(other.path_data.len()); let mut skips = FxHashSet::default(); for (other_pathid, other_path_data) in other.path_data.iter().enumerate() { if let Some(other_path_data) = other_path_data { - let mut fqp = other_path_data.module_path.clone(); let name = Symbol::intern(&other.names[other_pathid]); - fqp.push(name); + let fqp = + other_path_data.module_path.iter().copied().chain(iter::once(name)).collect(); let self_pathid = other_entryid_offset + other_pathid; let self_pathid = match self.crate_paths_index.entry((other_path_data.ty, fqp)) { Entry::Vacant(slot) => { @@ -1819,20 +1823,23 @@ pub(crate) fn build_index( tcx, ); } - let mut used_in_constraints = Vec::new(); - for constraint in &mut search_type.where_clause { - let mut used_in_constraint = BTreeSet::new(); - for trait_ in &mut constraint[..] { - convert_render_type( - trait_, - cache, - &mut serialized_index, - &mut used_in_constraint, - tcx, - ); - } - used_in_constraints.push(used_in_constraint); - } + let used_in_constraints = search_type + .where_clause + .iter_mut() + .map(|constraint| { + let mut used_in_constraint = BTreeSet::new(); + for trait_ in constraint { + convert_render_type( + trait_, + cache, + &mut serialized_index, + &mut used_in_constraint, + tcx, + ); + } + used_in_constraint + }) + .collect::>(); loop { let mut inserted_any = false; for (i, used_in_constraint) in used_in_constraints.iter().enumerate() { From 809a4b74e527b59bf55d351d0ea8e1304fd328f1 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sun, 23 Nov 2025 19:46:52 +0200 Subject: [PATCH 6/6] `simplify_fn_type` can only ever return 0 or 1 types, doesn't need to take `&mut Vec` --- src/librustdoc/html/render/search_index.rs | 354 +++++++++------------ 1 file changed, 143 insertions(+), 211 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 29f19ec6ca882..0c3b743ddcb14 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -2059,22 +2059,21 @@ enum SimplifiedParam { /// not be added to the map. /// /// This function also works recursively. -#[instrument(level = "trace", skip(tcx, res, rgen, cache))] +#[instrument(level = "trace", skip(tcx, rgen, cache))] fn simplify_fn_type<'a, 'tcx>( self_: Option<&'a Type>, generics: &Generics, arg: &'a Type, tcx: TyCtxt<'tcx>, recurse: usize, - res: &mut Vec, rgen: &mut FxIndexMap)>, is_return: bool, cache: &Cache, -) { +) -> Option { if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed // See #59502 for the original issue. - return; + return None; } // First, check if it's "Self". @@ -2091,179 +2090,120 @@ fn simplify_fn_type<'a, 'tcx>( match *arg { Type::Generic(arg_s) => { // First we check if the bounds are in a `where` predicate... - let mut type_bounds = Vec::new(); - for where_pred in generics.where_predicates.iter().filter(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, - _ => false, - }) { - let bounds = where_pred.get_bounds().unwrap_or(&[]); - for bound in bounds.iter() { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); + let where_bounds = generics + .where_predicates + .iter() + .filter_map(|g| { + if let WherePredicate::BoundPredicate { ty, bounds, .. } = g + && *ty == *arg + { + Some(bounds) + } else { + None } - } - } + }) + .flatten(); // Otherwise we check if the trait bounds are "inlined" like `T: Option`... - if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { - for bound in bound.get_bounds().unwrap_or(&[]) { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); - } - } - } - if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { - res.push(RenderType { - id: Some(RenderTypeId::Index(*idx)), - generics: None, - bindings: None, - }); + let inline_bounds = generics + .params + .iter() + .find(|g| g.is_type() && g.name == arg_s) + .and_then(|bound| bound.get_bounds()) + .into_iter() + .flatten(); + + let type_bounds = where_bounds + .chain(inline_bounds) + .filter_map( + |bound| if let Some(path) = bound.get_trait_path() { Some(path) } else { None }, + ) + .filter_map(|path| { + let ty = Type::Path { path }; + simplify_fn_type(self_, generics, &ty, tcx, recurse + 1, rgen, is_return, cache) + }) + .collect(); + + Some(if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { + RenderType { id: Some(RenderTypeId::Index(*idx)), generics: None, bindings: None } } else { let idx = -isize::try_from(rgen.len() + 1).unwrap(); rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } + RenderType { id: Some(RenderTypeId::Index(idx)), generics: None, bindings: None } + }) } Type::ImplTrait(ref bounds) => { - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { + let type_bounds = bounds + .iter() + .filter_map(|bound| bound.get_trait_path()) + .filter_map(|path| { let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); - } - } - if is_return && !type_bounds.is_empty() { + simplify_fn_type(self_, generics, &ty, tcx, recurse + 1, rgen, is_return, cache) + }) + .collect::>(); + Some(if is_return && !type_bounds.is_empty() { // In return position, `impl Trait` is a unique thing. - res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); + RenderType { id: None, generics: Some(type_bounds), bindings: None } } else { // In parameter position, `impl Trait` is the same as an unnamed generic parameter. let idx = -isize::try_from(rgen.len() + 1).unwrap(); rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } + RenderType { id: Some(RenderTypeId::Index(idx)), generics: None, bindings: None } + }) } Type::Slice(ref ty) => { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); + let ty_generics = + simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache) + .into_iter() + .collect(); + Some(get_index_type(arg, ty_generics, rgen)) } Type::Array(ref ty, _) => { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); + let ty_generics = + simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache) + .into_iter() + .collect(); + Some(get_index_type(arg, ty_generics, rgen)) } Type::Tuple(ref tys) => { - let mut ty_generics = Vec::new(); - for ty in tys { - simplify_fn_type( - self_, - generics, - ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - } - res.push(get_index_type(arg, ty_generics, rgen)); + let ty_generics = tys + .iter() + .filter_map(|ty| { + simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache) + }) + .collect(); + Some(get_index_type(arg, ty_generics, rgen)) } Type::BareFunction(ref bf) => { - let mut ty_generics = Vec::new(); - for ty in bf.decl.inputs.iter().map(|arg| &arg.type_) { - simplify_fn_type( - self_, - generics, - ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - } + let ty_generics = bf + .decl + .inputs + .iter() + .map(|arg| &arg.type_) + .filter_map(|ty| { + simplify_fn_type(self_, generics, ty, tcx, recurse + 1, rgen, is_return, cache) + }) + .collect(); // The search index, for simplicity's sake, represents fn pointers and closures // the same way: as a tuple for the parameters, and an associated type for the // return type. - let mut ty_output = Vec::new(); - simplify_fn_type( + let ty_output = simplify_fn_type( self_, generics, &bf.decl.output, tcx, recurse + 1, - &mut ty_output, rgen, is_return, cache, - ); + ) + .into_iter() + .collect(); let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; - res.push(RenderType { + Some(RenderType { id: get_index_type_id(arg, rgen), bindings: Some(ty_bindings), generics: Some(ty_generics), - }); + }) } Type::BorrowedRef { lifetime: _, mutability, ref type_ } | Type::RawPointer(mutability, ref type_) => { @@ -2275,18 +2215,12 @@ fn simplify_fn_type<'a, 'tcx>( bindings: None, }); } - simplify_fn_type( - self_, - generics, - type_, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); + if let Some(ty) = + simplify_fn_type(self_, generics, type_, tcx, recurse + 1, rgen, is_return, cache) + { + ty_generics.push(ty); + } + Some(get_index_type(arg, ty_generics, rgen)) } _ => { // This is not a type parameter. So for example if we have `T, U: Option`, and we're @@ -2297,22 +2231,25 @@ fn simplify_fn_type<'a, 'tcx>( let mut ty_generics = Vec::new(); let mut ty_constraints = Vec::new(); if let Some(arg_generics) = arg.generic_args() { - for ty in arg_generics.into_iter().filter_map(|param| match param { - clean::GenericArg::Type(ty) => Some(ty), - _ => None, - }) { - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - } + ty_generics = arg_generics + .into_iter() + .filter_map(|param| match param { + clean::GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .filter_map(|ty| { + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + rgen, + is_return, + cache, + ) + }) + .collect(); for constraint in arg_generics.constraints() { simplify_fn_constraint( self_, @@ -2359,9 +2296,10 @@ fn simplify_fn_type<'a, 'tcx>( // Can't just pass stored_bounds to simplify_fn_type, // because it also accepts rgen as a parameter. // Instead, have it fill in this local, then copy it into the map afterward. - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { + let type_bounds = bounds + .iter() + .filter_map(|bound| bound.get_trait_path()) + .filter_map(|path| { let ty = Type::Path { path }; simplify_fn_type( self_, @@ -2369,13 +2307,12 @@ fn simplify_fn_type<'a, 'tcx>( &ty, tcx, recurse + 1, - &mut type_bounds, rgen, is_return, cache, - ); - } - } + ) + }) + .collect(); let stored_bounds = &mut rgen .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) .unwrap() @@ -2397,11 +2334,13 @@ fn simplify_fn_type<'a, 'tcx>( } let id = get_index_type_id(arg, rgen); if id.is_some() || !ty_generics.is_empty() { - res.push(RenderType { + Some(RenderType { id, bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, - }); + }) + } else { + None } } } @@ -2422,17 +2361,18 @@ fn simplify_fn_constraint<'a>( let ty_constrained_assoc = RenderTypeId::AssociatedType(constraint.assoc.name); for param in &constraint.assoc.args { match param { - clean::GenericArg::Type(arg) => simplify_fn_type( - self_, - generics, - &arg, - tcx, - recurse + 1, - &mut ty_constraints, - rgen, - is_return, - cache, - ), + clean::GenericArg::Type(arg) => { + ty_constraints.extend(simplify_fn_type( + self_, + generics, + &arg, + tcx, + recurse + 1, + rgen, + is_return, + cache, + )); + } clean::GenericArg::Lifetime(_) | clean::GenericArg::Const(_) | clean::GenericArg::Infer => {} @@ -2454,34 +2394,32 @@ fn simplify_fn_constraint<'a>( match &constraint.kind { clean::AssocItemConstraintKind::Equality { term } => { if let clean::Term::Type(arg) = &term { - simplify_fn_type( + ty_constraints.extend(simplify_fn_type( self_, generics, arg, tcx, recurse + 1, - &mut ty_constraints, rgen, is_return, cache, - ); + )); } } clean::AssocItemConstraintKind::Bound { bounds } => { for bound in &bounds[..] { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; - simplify_fn_type( + ty_constraints.extend(simplify_fn_type( self_, generics, &ty, tcx, recurse + 1, - &mut ty_constraints, rgen, is_return, cache, - ); + )); } } } @@ -2537,23 +2475,17 @@ fn get_fn_inputs_and_outputs( (None, &func.generics) }; - let mut param_types = Vec::new(); - for param in decl.inputs.iter() { - simplify_fn_type( - self_, - generics, - ¶m.type_, - tcx, - 0, - &mut param_types, - &mut rgen, - false, - cache, - ); - } + let param_types = decl + .inputs + .iter() + .filter_map(|param| { + simplify_fn_type(self_, generics, ¶m.type_, tcx, 0, &mut rgen, false, cache) + }) + .collect(); - let mut ret_types = Vec::new(); - simplify_fn_type(self_, generics, &decl.output, tcx, 0, &mut ret_types, &mut rgen, true, cache); + let ret_types = simplify_fn_type(self_, generics, &decl.output, tcx, 0, &mut rgen, true, cache) + .into_iter() + .collect(); let mut simplified_params = rgen.into_iter().collect::>(); simplified_params.sort_by_key(|(_, (idx, _))| -idx);