avoid in-process serializing&deserializing

This commit is contained in:
Yotam Ofek 2025-10-06 16:55:14 +03:00
parent 4a54b26d30
commit eb8d87d1d8
2 changed files with 168 additions and 175 deletions

View file

@ -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<RenderTypeId>,
generics: Option<Vec<RenderType>>,
@ -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<RenderType>,
output: Vec<RenderType>,
@ -423,6 +425,75 @@ impl IndexItemFunctionType {
}
}
impl Serialize for IndexItemFunctionType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<Symbol>]);
impl<'a> Serialize for ParamNames<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<Self::Value, A::Error> {
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<Option<Symbol>> = v
.next_element()?
.map(|param_names: Vec<String>| {
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

View file

@ -34,7 +34,7 @@ pub(crate) struct SerializedSearchIndex {
path_data: Vec<Option<PathData>>,
entry_data: Vec<Option<EntryData>>,
descs: Vec<String>,
function_data: Vec<Option<FunctionData>>,
function_data: Vec<Option<IndexItemFunctionType>>,
alias_pointers: Vec<Option<usize>>,
// inverted index for concrete types and generics
type_data: Vec<Option<TypeData>>,
@ -61,7 +61,7 @@ impl SerializedSearchIndex {
let mut path_data: Vec<Option<PathData>> = Vec::new();
let mut entry_data: Vec<Option<EntryData>> = Vec::new();
let mut descs: Vec<String> = Vec::new();
let mut function_data: Vec<Option<FunctionData>> = Vec::new();
let mut function_data: Vec<Option<IndexItemFunctionType>> = Vec::new();
let mut type_data: Vec<Option<TypeData>> = Vec::new();
let mut alias_pointers: Vec<Option<usize>> = Vec::new();
@ -207,7 +207,7 @@ impl SerializedSearchIndex {
path_data: Option<PathData>,
entry_data: Option<EntryData>,
desc: String,
function_data: Option<FunctionData>,
function_data: Option<IndexItemFunctionType>,
type_data: Option<TypeData>,
alias_pointer: Option<usize>,
) -> 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<usize>,
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<usize>,
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 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 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<usize, usize>, 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<usize, usize>, 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!(),
}
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 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<String>,
}
impl Serialize for FunctionData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<FunctionData, D::Error>
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<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<FunctionData, A::Error> {
let function_signature: String = v
.next_element()?
.ok_or_else(|| A::Error::missing_field("function_signature"))?;
let param_names: Vec<String> =
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::<Vec<String>>(),
});
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());