Auto merge of #92395 - Kobzol:rustdoc-bindings-thin-vec, r=camelid
Rustdoc: use ThinVec for GenericArgs bindings The bindings are almost always empty. This reduces the size of `PathSegment` and `GenericArgs` by about one fourth.
This commit is contained in:
commit
b5da80871d
4 changed files with 18 additions and 12 deletions
|
@ -5,7 +5,7 @@ use std::iter::FromIterator;
|
||||||
/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
|
/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
|
||||||
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
|
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
|
||||||
/// which uses only a single (null) pointer.
|
/// which uses only a single (null) pointer.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
|
||||||
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
|
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
|
||||||
|
|
||||||
impl<T> ThinVec<T> {
|
impl<T> ThinVec<T> {
|
||||||
|
@ -20,6 +20,13 @@ impl<T> ThinVec<T> {
|
||||||
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
|
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
|
||||||
self.into_iter()
|
self.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, item: T) {
|
||||||
|
match *self {
|
||||||
|
ThinVec(Some(ref mut vec)) => vec.push(item),
|
||||||
|
ThinVec(None) => *self = vec![item].into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<Vec<T>> for ThinVec<T> {
|
impl<T> From<Vec<T>> for ThinVec<T> {
|
||||||
|
@ -101,10 +108,7 @@ impl<T> Extend<T> for ThinVec<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_one(&mut self, item: T) {
|
fn extend_one(&mut self, item: T) {
|
||||||
match *self {
|
self.push(item)
|
||||||
ThinVec(Some(ref mut vec)) => vec.push(item),
|
|
||||||
ThinVec(None) => *self = vec![item].into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_reserve(&mut self, additional: usize) {
|
fn extend_reserve(&mut self, additional: usize) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_data_structures::thin_vec::ThinVec;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -540,7 +541,7 @@ fn build_module(
|
||||||
name: prim_ty.as_sym(),
|
name: prim_ty.as_sym(),
|
||||||
args: clean::GenericArgs::AngleBracketed {
|
args: clean::GenericArgs::AngleBracketed {
|
||||||
args: Vec::new(),
|
args: Vec::new(),
|
||||||
bindings: Vec::new(),
|
bindings: ThinVec::new(),
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
|
|
|
@ -2060,14 +2060,14 @@ rustc_data_structures::static_assert_size!(GenericArg, 80);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
crate enum GenericArgs {
|
crate enum GenericArgs {
|
||||||
AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
|
AngleBracketed { args: Vec<GenericArg>, bindings: ThinVec<TypeBinding> },
|
||||||
Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
|
Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
|
||||||
}
|
}
|
||||||
|
|
||||||
// `GenericArgs` is in every `PathSegment`, so its size can significantly
|
// `GenericArgs` is in every `PathSegment`, so its size can significantly
|
||||||
// affect rustdoc's memory usage.
|
// affect rustdoc's memory usage.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(GenericArgs, 56);
|
rustc_data_structures::static_assert_size!(GenericArgs, 40);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
crate struct PathSegment {
|
crate struct PathSegment {
|
||||||
|
@ -2078,7 +2078,7 @@ crate struct PathSegment {
|
||||||
// `PathSegment` usually occurs multiple times in every `Path`, so its size can
|
// `PathSegment` usually occurs multiple times in every `Path`, so its size can
|
||||||
// significantly affect rustdoc's memory usage.
|
// significantly affect rustdoc's memory usage.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(PathSegment, 64);
|
rustc_data_structures::static_assert_size!(PathSegment, 48);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
crate struct Typedef {
|
crate struct Typedef {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::visit_lib::LibEmbargoVisitor;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::tokenstream::TokenTree;
|
use rustc_ast::tokenstream::TokenTree;
|
||||||
|
use rustc_data_structures::thin_vec::ThinVec;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
@ -108,7 +109,7 @@ fn external_generic_args(
|
||||||
if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
|
if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
|
||||||
let inputs = match ty_kind.unwrap() {
|
let inputs = match ty_kind.unwrap() {
|
||||||
ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
|
ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
|
||||||
_ => return GenericArgs::AngleBracketed { args, bindings },
|
_ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
|
||||||
};
|
};
|
||||||
let output = None;
|
let output = None;
|
||||||
// FIXME(#20299) return type comes from a projection now
|
// FIXME(#20299) return type comes from a projection now
|
||||||
|
@ -118,7 +119,7 @@ fn external_generic_args(
|
||||||
// };
|
// };
|
||||||
GenericArgs::Parenthesized { inputs, output }
|
GenericArgs::Parenthesized { inputs, output }
|
||||||
} else {
|
} else {
|
||||||
GenericArgs::AngleBracketed { args, bindings }
|
GenericArgs::AngleBracketed { args, bindings: bindings.into() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ pub(super) fn external_path(
|
||||||
/// Remove the generic arguments from a path.
|
/// Remove the generic arguments from a path.
|
||||||
crate fn strip_path_generics(mut path: Path) -> Path {
|
crate fn strip_path_generics(mut path: Path) -> Path {
|
||||||
for ps in path.segments.iter_mut() {
|
for ps in path.segments.iter_mut() {
|
||||||
ps.args = GenericArgs::AngleBracketed { args: vec![], bindings: vec![] }
|
ps.args = GenericArgs::AngleBracketed { args: vec![], bindings: ThinVec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
path
|
path
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue