Skip to content

Commit b5da808

Browse files
committed
Auto merge of rust-lang#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.
2 parents 8f3238f + 3d8d3f1 commit b5da808

File tree

4 files changed

+18
-12
lines changed

4 files changed

+18
-12
lines changed

compiler/rustc_data_structures/src/thin_vec.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::iter::FromIterator;
55
/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
66
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
77
/// which uses only a single (null) pointer.
8-
#[derive(Clone, Encodable, Decodable, Debug)]
8+
#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
99
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
1010

1111
impl<T> ThinVec<T> {
@@ -20,6 +20,13 @@ impl<T> ThinVec<T> {
2020
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
2121
self.into_iter()
2222
}
23+
24+
pub fn push(&mut self, item: T) {
25+
match *self {
26+
ThinVec(Some(ref mut vec)) => vec.push(item),
27+
ThinVec(None) => *self = vec![item].into(),
28+
}
29+
}
2330
}
2431

2532
impl<T> From<Vec<T>> for ThinVec<T> {
@@ -101,10 +108,7 @@ impl<T> Extend<T> for ThinVec<T> {
101108
}
102109

103110
fn extend_one(&mut self, item: T) {
104-
match *self {
105-
ThinVec(Some(ref mut vec)) => vec.push(item),
106-
ThinVec(None) => *self = vec![item].into(),
107-
}
111+
self.push(item)
108112
}
109113

110114
fn extend_reserve(&mut self, additional: usize) {

src/librustdoc/clean/inline.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::sync::Arc;
55

66
use rustc_ast as ast;
77
use rustc_data_structures::fx::FxHashSet;
8+
use rustc_data_structures::thin_vec::ThinVec;
89
use rustc_hir as hir;
910
use rustc_hir::def::{DefKind, Res};
1011
use rustc_hir::def_id::DefId;
@@ -540,7 +541,7 @@ fn build_module(
540541
name: prim_ty.as_sym(),
541542
args: clean::GenericArgs::AngleBracketed {
542543
args: Vec::new(),
543-
bindings: Vec::new(),
544+
bindings: ThinVec::new(),
544545
},
545546
}],
546547
},

src/librustdoc/clean/types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2060,14 +2060,14 @@ rustc_data_structures::static_assert_size!(GenericArg, 80);
20602060

20612061
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
20622062
crate enum GenericArgs {
2063-
AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2063+
AngleBracketed { args: Vec<GenericArg>, bindings: ThinVec<TypeBinding> },
20642064
Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
20652065
}
20662066

20672067
// `GenericArgs` is in every `PathSegment`, so its size can significantly
20682068
// affect rustdoc's memory usage.
20692069
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2070-
rustc_data_structures::static_assert_size!(GenericArgs, 56);
2070+
rustc_data_structures::static_assert_size!(GenericArgs, 40);
20712071

20722072
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
20732073
crate struct PathSegment {
@@ -2078,7 +2078,7 @@ crate struct PathSegment {
20782078
// `PathSegment` usually occurs multiple times in every `Path`, so its size can
20792079
// significantly affect rustdoc's memory usage.
20802080
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2081-
rustc_data_structures::static_assert_size!(PathSegment, 64);
2081+
rustc_data_structures::static_assert_size!(PathSegment, 48);
20822082

20832083
#[derive(Clone, Debug)]
20842084
crate struct Typedef {

src/librustdoc/clean/utils.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::visit_lib::LibEmbargoVisitor;
1010

1111
use rustc_ast as ast;
1212
use rustc_ast::tokenstream::TokenTree;
13+
use rustc_data_structures::thin_vec::ThinVec;
1314
use rustc_hir as hir;
1415
use rustc_hir::def::{DefKind, Res};
1516
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -108,7 +109,7 @@ fn external_generic_args(
108109
if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
109110
let inputs = match ty_kind.unwrap() {
110111
ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
111-
_ => return GenericArgs::AngleBracketed { args, bindings },
112+
_ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
112113
};
113114
let output = None;
114115
// FIXME(#20299) return type comes from a projection now
@@ -118,7 +119,7 @@ fn external_generic_args(
118119
// };
119120
GenericArgs::Parenthesized { inputs, output }
120121
} else {
121-
GenericArgs::AngleBracketed { args, bindings }
122+
GenericArgs::AngleBracketed { args, bindings: bindings.into() }
122123
}
123124
}
124125

@@ -143,7 +144,7 @@ pub(super) fn external_path(
143144
/// Remove the generic arguments from a path.
144145
crate fn strip_path_generics(mut path: Path) -> Path {
145146
for ps in path.segments.iter_mut() {
146-
ps.args = GenericArgs::AngleBracketed { args: vec![], bindings: vec![] }
147+
ps.args = GenericArgs::AngleBracketed { args: vec![], bindings: ThinVec::new() }
147148
}
148149

149150
path

0 commit comments

Comments
 (0)