From 3407d8b1990ab820a6964436c48d2c2e8c226b7a Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Mon, 6 Oct 2025 16:55:14 +0300 Subject: [PATCH] avoid in-process serializing&deserializing --- src/librustdoc/html/render/mod.rs | 75 +++++- src/librustdoc/html/render/search_index.rs | 268 ++++++++------------- 2 files changed, 168 insertions(+), 175 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 84d684e0c95f9..52617b6c43204 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -61,6 +61,8 @@ use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{BytePos, DUMMY_SP, FileName, RealFileName}; +use serde::ser::SerializeSeq as _; +use serde::{Deserialize, Serialize}; use tracing::{debug, info}; pub(crate) use self::context::*; @@ -144,7 +146,7 @@ pub(crate) struct IndexItem { } /// A type used for the search index. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] struct RenderType { id: Option, generics: Option>, @@ -301,7 +303,7 @@ impl RenderTypeId { } /// Full type of functions/methods in the search index. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct IndexItemFunctionType { inputs: Vec, output: Vec, @@ -423,6 +425,75 @@ impl IndexItemFunctionType { } } +impl Serialize for IndexItemFunctionType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut seq = serializer.serialize_seq(Some(2))?; + let mut fn_type = String::new(); + self.write_to_string_without_param_names(&mut fn_type); + seq.serialize_element(&fn_type)?; + + struct ParamNames<'a>(&'a [Option]); + + impl<'a> Serialize for ParamNames<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.collect_seq( + self.0 + .iter() + .map(|symbol| symbol.as_ref().map(ToString::to_string).unwrap_or_default()), + ) + } + } + + seq.serialize_element(&ParamNames(&self.param_names))?; + seq.end() + } +} + +impl<'de> Deserialize<'de> for IndexItemFunctionType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::{self, Error as _}; + + struct FunctionDataVisitor; + impl<'de> de::Visitor<'de> for FunctionDataVisitor { + type Value = IndexItemFunctionType; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "fn data") + } + fn visit_seq>(self, mut v: A) -> Result { + let (mut function_signature, _) = v + .next_element()? + .map(|fn_: String| { + IndexItemFunctionType::read_from_string_without_param_names(fn_.as_bytes()) + }) + .ok_or_else(|| A::Error::missing_field("function_signature"))?; + let param_names: Vec> = v + .next_element()? + .map(|param_names: Vec| { + param_names + .into_iter() + .map(|symbol| { + if symbol.is_empty() { None } else { Some(Symbol::intern(&symbol)) } + }) + .collect() + }) + .ok_or_else(|| A::Error::missing_field("param_names"))?; + function_signature.param_names = param_names; + Ok(function_signature) + } + } + deserializer.deserialize_any(FunctionDataVisitor) + } +} + #[derive(Debug, Clone)] pub(crate) struct StylePath { /// The path to the theme diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 253d90294687e..080faff3a6de6 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -34,7 +34,7 @@ pub(crate) struct SerializedSearchIndex { path_data: Vec>, entry_data: Vec>, descs: Vec, - function_data: Vec>, + function_data: Vec>, alias_pointers: Vec>, // inverted index for concrete types and generics type_data: Vec>, @@ -61,7 +61,7 @@ impl SerializedSearchIndex { let mut path_data: Vec> = Vec::new(); let mut entry_data: Vec> = Vec::new(); let mut descs: Vec = Vec::new(); - let mut function_data: Vec> = Vec::new(); + let mut function_data: Vec> = Vec::new(); let mut type_data: Vec> = Vec::new(); let mut alias_pointers: Vec> = Vec::new(); @@ -207,7 +207,7 @@ impl SerializedSearchIndex { path_data: Option, entry_data: Option, desc: String, - function_data: Option, + function_data: Option, type_data: Option, alias_pointer: Option, ) -> usize { @@ -446,73 +446,62 @@ impl SerializedSearchIndex { ..other_entry_data.clone() }), other.descs[other_entryid].clone(), - other.function_data[other_entryid].as_ref().map(|function_data| FunctionData { - function_signature: { - let (mut func, _offset) = - IndexItemFunctionType::read_from_string_without_param_names( - function_data.function_signature.as_bytes(), - ); - fn map_fn_sig_item( - map_other_pathid_to_self_pathid: &mut Vec, - ty: &mut RenderType, - ) { - match ty.id { - None => {} - Some(RenderTypeId::Index(generic)) if generic < 0 => {} - Some(RenderTypeId::Index(id)) => { - let id = usize::try_from(id).unwrap(); - let id = map_other_pathid_to_self_pathid[id]; - assert!(id != !0); - ty.id = - Some(RenderTypeId::Index(isize::try_from(id).unwrap())); - } - _ => unreachable!(), + other.function_data[other_entryid].clone().map(|mut func| { + fn map_fn_sig_item( + map_other_pathid_to_self_pathid: &mut Vec, + ty: &mut RenderType, + ) { + match ty.id { + None => {} + Some(RenderTypeId::Index(generic)) if generic < 0 => {} + Some(RenderTypeId::Index(id)) => { + let id = usize::try_from(id).unwrap(); + let id = map_other_pathid_to_self_pathid[id]; + assert!(id != !0); + ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap())); } - if let Some(generics) = &mut ty.generics { - for generic in generics { - map_fn_sig_item(map_other_pathid_to_self_pathid, generic); - } + _ => unreachable!(), + } + if let Some(generics) = &mut ty.generics { + for generic in generics { + map_fn_sig_item(map_other_pathid_to_self_pathid, generic); } - if let Some(bindings) = &mut ty.bindings { - for (param, constraints) in bindings { - *param = match *param { - param @ RenderTypeId::Index(generic) if generic < 0 => { - param - } - RenderTypeId::Index(id) => { - let id = usize::try_from(id).unwrap(); - let id = map_other_pathid_to_self_pathid[id]; - assert!(id != !0); - RenderTypeId::Index(isize::try_from(id).unwrap()) - } - _ => unreachable!(), - }; - for constraint in constraints { - map_fn_sig_item( - map_other_pathid_to_self_pathid, - constraint, - ); + } + if let Some(bindings) = &mut ty.bindings { + for (param, constraints) in bindings { + *param = match *param { + param @ RenderTypeId::Index(generic) if generic < 0 => { + param + } + RenderTypeId::Index(id) => { + let id = usize::try_from(id).unwrap(); + let id = map_other_pathid_to_self_pathid[id]; + assert!(id != !0); + RenderTypeId::Index(isize::try_from(id).unwrap()) } + _ => unreachable!(), + }; + for constraint in constraints { + map_fn_sig_item( + map_other_pathid_to_self_pathid, + constraint, + ); } } } - for input in &mut func.inputs { - map_fn_sig_item(&mut 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); - } - for clause in &mut func.where_clause { - for entry in clause { - map_fn_sig_item(&mut map_other_pathid_to_self_pathid, entry); - } + } + for input in &mut func.inputs { + map_fn_sig_item(&mut 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); + } + for clause in &mut func.where_clause { + for entry in clause { + map_fn_sig_item(&mut map_other_pathid_to_self_pathid, entry); } - let mut result = - String::with_capacity(function_data.function_signature.len()); - func.write_to_string_without_param_names(&mut result); - result - }, - param_names: function_data.param_names.clone(), + } + func }), other.type_data[other_entryid].as_ref().map(|type_data| TypeData { inverted_function_inputs_index: type_data @@ -626,69 +615,55 @@ impl SerializedSearchIndex { }, ), self.descs[id].clone(), - self.function_data[id].as_ref().map( - |FunctionData { function_signature, param_names }| FunctionData { - function_signature: { - let (mut func, _offset) = - IndexItemFunctionType::read_from_string_without_param_names( - function_signature.as_bytes(), - ); - fn map_fn_sig_item(map: &FxHashMap, ty: &mut RenderType) { - match ty.id { - None => {} - Some(RenderTypeId::Index(generic)) if generic < 0 => {} - Some(RenderTypeId::Index(id)) => { + self.function_data[id].clone().map(|mut func| { + fn map_fn_sig_item(map: &FxHashMap, ty: &mut RenderType) { + match ty.id { + None => {} + Some(RenderTypeId::Index(generic)) if generic < 0 => {} + Some(RenderTypeId::Index(id)) => { + let id = usize::try_from(id).unwrap(); + let id = *map.get(&id).unwrap(); + assert!(id != !0); + ty.id = Some(RenderTypeId::Index(isize::try_from(id).unwrap())); + } + _ => unreachable!(), + } + if let Some(generics) = &mut ty.generics { + for generic in generics { + map_fn_sig_item(map, generic); + } + } + if let Some(bindings) = &mut ty.bindings { + for (param, constraints) in bindings { + *param = match *param { + param @ RenderTypeId::Index(generic) if generic < 0 => param, + RenderTypeId::Index(id) => { let id = usize::try_from(id).unwrap(); let id = *map.get(&id).unwrap(); assert!(id != !0); - ty.id = - Some(RenderTypeId::Index(isize::try_from(id).unwrap())); + RenderTypeId::Index(isize::try_from(id).unwrap()) } _ => unreachable!(), + }; + for constraint in constraints { + map_fn_sig_item(map, constraint); } - if let Some(generics) = &mut ty.generics { - for generic in generics { - map_fn_sig_item(map, generic); - } - } - if let Some(bindings) = &mut ty.bindings { - for (param, constraints) in bindings { - *param = match *param { - param @ RenderTypeId::Index(generic) if generic < 0 => { - param - } - RenderTypeId::Index(id) => { - let id = usize::try_from(id).unwrap(); - let id = *map.get(&id).unwrap(); - assert!(id != !0); - RenderTypeId::Index(isize::try_from(id).unwrap()) - } - _ => unreachable!(), - }; - for constraint in constraints { - map_fn_sig_item(map, constraint); - } - } - } - } - for input in &mut func.inputs { - map_fn_sig_item(&map, input); - } - for output in &mut func.output { - map_fn_sig_item(&map, output); } - for clause in &mut func.where_clause { - for entry in clause { - map_fn_sig_item(&map, entry); - } - } - let mut result = String::with_capacity(function_signature.len()); - func.write_to_string_without_param_names(&mut result); - result - }, - param_names: param_names.clone(), - }, - ), + } + } + for input in &mut func.inputs { + map_fn_sig_item(&map, input); + } + for output in &mut func.output { + map_fn_sig_item(&map, output); + } + for clause in &mut func.where_clause { + for entry in clause { + map_fn_sig_item(&map, entry); + } + } + func + }), self.type_data[id].as_ref().map( |TypeData { search_unbox, @@ -1259,48 +1234,6 @@ impl<'de> Deserialize<'de> for SerializedOptional32 { } } -#[derive(Clone, Debug)] -pub struct FunctionData { - function_signature: String, - param_names: Vec, -} - -impl Serialize for FunctionData { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&self.function_signature)?; - seq.serialize_element(&self.param_names)?; - seq.end() - } -} - -impl<'de> Deserialize<'de> for FunctionData { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct FunctionDataVisitor; - impl<'de> de::Visitor<'de> for FunctionDataVisitor { - type Value = FunctionData; - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "fn data") - } - fn visit_seq>(self, mut v: A) -> Result { - let function_signature: String = v - .next_element()? - .ok_or_else(|| A::Error::missing_field("function_signature"))?; - let param_names: Vec = - v.next_element()?.ok_or_else(|| A::Error::missing_field("param_names"))?; - Ok(FunctionData { function_signature, param_names }) - } - } - deserializer.deserialize_any(FunctionDataVisitor) - } -} - /// Builds the search index from the collected metadata pub(crate) fn build_index( krate: &clean::Crate, @@ -1927,18 +1860,7 @@ pub(crate) fn build_index( // because the postings list has to fill in an empty array for each // unoccupied size. if item.ty.is_fn_like() { 0 } else { 16 }; - serialized_index.function_data[new_entry_id] = Some(FunctionData { - function_signature: { - let mut function_signature = String::new(); - search_type.write_to_string_without_param_names(&mut function_signature); - function_signature - }, - param_names: search_type - .param_names - .iter() - .map(|sym| sym.map(|sym| sym.to_string()).unwrap_or(String::new())) - .collect::>(), - }); + 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());