Skip to content

Commit 3f63848

Browse files
Shrink TypeRef from 16 from 32 bytes
Only references and arrays need to be boxed, and they comprise only 9.4% of the types (according to counting on r-a's code). This saves 17mb.
1 parent fd7648d commit 3f63848

File tree

10 files changed

+178
-149
lines changed

10 files changed

+178
-149
lines changed

src/tools/rust-analyzer/crates/hir-def/src/generics.rs

+52-49
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use hir_expand::{
1111
ExpandResult,
1212
};
1313
use la_arena::{Arena, RawIdx};
14-
use stdx::impl_from;
14+
use stdx::{
15+
impl_from,
16+
thin_vec::{EmptyOptimizedThinVec, ThinVec},
17+
};
1518
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
1619
use triomphe::Arc;
1720

@@ -22,7 +25,10 @@ use crate::{
2225
lower::LowerCtx,
2326
nameres::{DefMap, MacroSubNs},
2427
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
25-
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
28+
type_ref::{
29+
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
30+
TypesSourceMap,
31+
},
2632
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
2733
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
2834
};
@@ -590,18 +596,18 @@ impl GenericParamsCollector {
590596
self.where_predicates.push(predicate);
591597
}
592598

593-
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<TypeBound>>) {
599+
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<ThinVec<TypeBound>>) {
594600
for bounds in impl_bounds {
595601
let param = TypeParamData {
596602
name: None,
597603
default: None,
598604
provenance: TypeParamProvenance::ArgumentImplTrait,
599605
};
600606
let param_id = self.type_or_consts.alloc(param.into());
601-
for bound in bounds {
607+
for bound in &bounds {
602608
self.where_predicates.push(WherePredicate::TypeBound {
603609
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
604-
bound,
610+
bound: bound.clone(),
605611
});
606612
}
607613
}
@@ -725,46 +731,45 @@ fn copy_type_ref(
725731
to_source_map: &mut TypesSourceMap,
726732
) -> TypeRefId {
727733
let result = match &from[type_ref] {
728-
&TypeRef::Fn { ref params, is_varargs, is_unsafe, ref abi } => {
729-
let params = params
730-
.iter()
731-
.map(|(name, param_type)| {
732-
(
733-
name.clone(),
734-
copy_type_ref(*param_type, from, from_source_map, to, to_source_map),
735-
)
736-
})
737-
.collect();
738-
TypeRef::Fn { params, is_varargs, is_unsafe, abi: abi.clone() }
734+
TypeRef::Fn(fn_) => {
735+
let params = fn_.params().iter().map(|(name, param_type)| {
736+
(name.clone(), copy_type_ref(*param_type, from, from_source_map, to, to_source_map))
737+
});
738+
TypeRef::Fn(FnType::new(fn_.is_varargs(), fn_.is_unsafe(), fn_.abi().clone(), params))
739739
}
740-
TypeRef::Tuple(types) => TypeRef::Tuple(
741-
types
742-
.iter()
743-
.map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map))
744-
.collect(),
745-
),
740+
TypeRef::Tuple(types) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
741+
types.iter().map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map)),
742+
)),
746743
&TypeRef::RawPtr(type_ref, mutbl) => TypeRef::RawPtr(
747744
copy_type_ref(type_ref, from, from_source_map, to, to_source_map),
748745
mutbl,
749746
),
750-
TypeRef::Reference(type_ref, lifetime, mutbl) => TypeRef::Reference(
751-
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map),
752-
lifetime.clone(),
753-
*mutbl,
754-
),
755-
TypeRef::Array(type_ref, len) => TypeRef::Array(
756-
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map),
757-
len.clone(),
758-
),
747+
TypeRef::Reference(ref_) => TypeRef::Reference(Box::new(RefType {
748+
ty: copy_type_ref(ref_.ty, from, from_source_map, to, to_source_map),
749+
lifetime: ref_.lifetime.clone(),
750+
mutability: ref_.mutability,
751+
})),
752+
TypeRef::Array(array) => TypeRef::Array(Box::new(ArrayType {
753+
ty: copy_type_ref(array.ty, from, from_source_map, to, to_source_map),
754+
len: array.len.clone(),
755+
})),
759756
&TypeRef::Slice(type_ref) => {
760757
TypeRef::Slice(copy_type_ref(type_ref, from, from_source_map, to, to_source_map))
761758
}
762-
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(
763-
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(),
764-
),
765-
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(
766-
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(),
767-
),
759+
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(ThinVec::from_iter(copy_type_bounds(
760+
bounds,
761+
from,
762+
from_source_map,
763+
to,
764+
to_source_map,
765+
))),
766+
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(ThinVec::from_iter(copy_type_bounds(
767+
bounds,
768+
from,
769+
from_source_map,
770+
to,
771+
to_source_map,
772+
))),
768773
TypeRef::Path(path) => {
769774
TypeRef::Path(copy_path(path, from, from_source_map, to, to_source_map))
770775
}
@@ -833,7 +838,8 @@ fn copy_generic_args(
833838
copy_type_ref(type_ref, from, from_source_map, to, to_source_map)
834839
});
835840
let bounds =
836-
copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map);
841+
copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map)
842+
.collect();
837843
AssociatedTypeBinding { name, args, type_ref, bounds }
838844
})
839845
.collect();
@@ -846,17 +852,14 @@ fn copy_generic_args(
846852
})
847853
}
848854

849-
fn copy_type_bounds(
850-
bounds: &[TypeBound],
851-
from: &TypesMap,
852-
from_source_map: &TypesSourceMap,
853-
to: &mut TypesMap,
854-
to_source_map: &mut TypesSourceMap,
855-
) -> Box<[TypeBound]> {
856-
bounds
857-
.iter()
858-
.map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
859-
.collect()
855+
fn copy_type_bounds<'a>(
856+
bounds: &'a [TypeBound],
857+
from: &'a TypesMap,
858+
from_source_map: &'a TypesSourceMap,
859+
to: &'a mut TypesMap,
860+
to_source_map: &'a mut TypesSourceMap,
861+
) -> impl stdx::thin_vec::TrustedLen<Item = TypeBound> + 'a {
862+
bounds.iter().map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
860863
}
861864

862865
fn copy_type_bound(

src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs

+54-34
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use hir_expand::{
1212
use intern::{sym, Symbol};
1313
use la_arena::{Arena, ArenaMap, Idx};
1414
use span::Edition;
15+
use stdx::thin_vec::{thin_vec_with_header_struct, EmptyOptimizedThinVec, ThinVec};
1516
use syntax::{
1617
ast::{self, HasGenericArgs, HasName, IsString},
1718
AstPtr,
@@ -108,31 +109,51 @@ impl TraitRef {
108109
}
109110
}
110111

112+
thin_vec_with_header_struct! {
113+
pub new(pub(crate)) struct FnType, FnTypeHeader {
114+
pub params: [(Option<Name>, TypeRefId)],
115+
pub is_varargs: bool,
116+
pub is_unsafe: bool,
117+
pub abi: Option<Symbol>; ref,
118+
}
119+
}
120+
121+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
122+
pub struct ArrayType {
123+
pub ty: TypeRefId,
124+
// FIXME: This should be Ast<ConstArg>
125+
pub len: ConstRef,
126+
}
127+
128+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
129+
pub struct RefType {
130+
pub ty: TypeRefId,
131+
pub lifetime: Option<LifetimeRef>,
132+
pub mutability: Mutability,
133+
}
134+
111135
/// Compare ty::Ty
112136
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
113137
pub enum TypeRef {
114138
Never,
115139
Placeholder,
116-
Tuple(Vec<TypeRefId>),
140+
Tuple(EmptyOptimizedThinVec<TypeRefId>),
117141
Path(Path),
118142
RawPtr(TypeRefId, Mutability),
119-
Reference(TypeRefId, Option<LifetimeRef>, Mutability),
120-
// FIXME: This should be Array(TypeRefId, Ast<ConstArg>),
121-
Array(TypeRefId, ConstRef),
143+
Reference(Box<RefType>),
144+
Array(Box<ArrayType>),
122145
Slice(TypeRefId),
123146
/// A fn pointer. Last element of the vector is the return type.
124-
Fn {
125-
params: Box<[(Option<Name>, TypeRefId)]>,
126-
is_varargs: bool,
127-
is_unsafe: bool,
128-
abi: Option<Symbol>,
129-
},
130-
ImplTrait(Vec<TypeBound>),
131-
DynTrait(Vec<TypeBound>),
147+
Fn(FnType),
148+
ImplTrait(ThinVec<TypeBound>),
149+
DynTrait(ThinVec<TypeBound>),
132150
Macro(AstId<ast::MacroCall>),
133151
Error,
134152
}
135153

154+
#[cfg(target_arch = "x86_64")]
155+
const _: () = assert!(size_of::<TypeRef>() == 16);
156+
136157
pub type TypeRefId = Idx<TypeRef>;
137158

138159
#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
@@ -222,9 +243,9 @@ impl TypeRef {
222243
pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId {
223244
let ty = match &node {
224245
ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
225-
ast::Type::TupleType(inner) => {
226-
TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
227-
}
246+
ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
247+
Vec::from_iter(inner.fields().map(|it| TypeRef::from_ast(ctx, it))),
248+
)),
228249
ast::Type::NeverType(..) => TypeRef::Never,
229250
ast::Type::PathType(inner) => {
230251
// FIXME: Use `Path::from_src`
@@ -241,22 +262,25 @@ impl TypeRef {
241262
}
242263
ast::Type::ArrayType(inner) => {
243264
let len = ConstRef::from_const_arg(ctx, inner.const_arg());
244-
TypeRef::Array(TypeRef::from_ast_opt(ctx, inner.ty()), len)
265+
TypeRef::Array(Box::new(ArrayType {
266+
ty: TypeRef::from_ast_opt(ctx, inner.ty()),
267+
len,
268+
}))
245269
}
246270
ast::Type::SliceType(inner) => TypeRef::Slice(TypeRef::from_ast_opt(ctx, inner.ty())),
247271
ast::Type::RefType(inner) => {
248272
let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty());
249273
let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt));
250274
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
251-
TypeRef::Reference(inner_ty, lifetime, mutability)
275+
TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
252276
}
253277
ast::Type::InferType(_inner) => TypeRef::Placeholder,
254278
ast::Type::FnPtrType(inner) => {
255279
let ret_ty = inner
256280
.ret_type()
257281
.and_then(|rt| rt.ty())
258282
.map(|it| TypeRef::from_ast(ctx, it))
259-
.unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::Tuple(Vec::new())));
283+
.unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::unit()));
260284
let mut is_varargs = false;
261285
let mut params = if let Some(pl) = inner.param_list() {
262286
if let Some(param) = pl.params().last() {
@@ -288,12 +312,7 @@ impl TypeRef {
288312

289313
let abi = inner.abi().map(lower_abi);
290314
params.push((None, ret_ty));
291-
TypeRef::Fn {
292-
params: params.into(),
293-
is_varargs,
294-
is_unsafe: inner.unsafe_token().is_some(),
295-
abi,
296-
}
315+
TypeRef::Fn(FnType::new(is_varargs, inner.unsafe_token().is_some(), abi, params))
297316
}
298317
// for types are close enough for our purposes to the inner type for now...
299318
ast::Type::ForType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -325,7 +344,7 @@ impl TypeRef {
325344
}
326345

327346
pub(crate) fn unit() -> TypeRef {
328-
TypeRef::Tuple(Vec::new())
347+
TypeRef::Tuple(EmptyOptimizedThinVec::empty())
329348
}
330349

331350
pub fn walk(this: TypeRefId, map: &TypesMap, f: &mut impl FnMut(&TypeRef)) {
@@ -335,14 +354,13 @@ impl TypeRef {
335354
let type_ref = &map[type_ref];
336355
f(type_ref);
337356
match type_ref {
338-
TypeRef::Fn { params, is_varargs: _, is_unsafe: _, abi: _ } => {
339-
params.iter().for_each(|&(_, param_type)| go(param_type, f, map))
357+
TypeRef::Fn(fn_) => {
358+
fn_.params().iter().for_each(|&(_, param_type)| go(param_type, f, map))
340359
}
341360
TypeRef::Tuple(types) => types.iter().for_each(|&t| go(t, f, map)),
342-
TypeRef::RawPtr(type_ref, _)
343-
| TypeRef::Reference(type_ref, ..)
344-
| TypeRef::Array(type_ref, _)
345-
| TypeRef::Slice(type_ref) => go(*type_ref, f, map),
361+
TypeRef::RawPtr(type_ref, _) | TypeRef::Slice(type_ref) => go(*type_ref, f, map),
362+
TypeRef::Reference(it) => go(it.ty, f, map),
363+
TypeRef::Array(it) => go(it.ty, f, map),
346364
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
347365
for bound in bounds {
348366
match bound {
@@ -394,11 +412,13 @@ impl TypeRef {
394412
pub(crate) fn type_bounds_from_ast(
395413
lower_ctx: &LowerCtx<'_>,
396414
type_bounds_opt: Option<ast::TypeBoundList>,
397-
) -> Vec<TypeBound> {
415+
) -> ThinVec<TypeBound> {
398416
if let Some(type_bounds) = type_bounds_opt {
399-
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
417+
ThinVec::from_iter(Vec::from_iter(
418+
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)),
419+
))
400420
} else {
401-
vec![]
421+
ThinVec::from_iter([])
402422
}
403423
}
404424

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

+18-17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use intern::{sym, Symbol};
1212
use la_arena::Arena;
1313
use rustc_hash::FxHashMap;
1414
use span::{AstIdMap, SyntaxContextId};
15+
use stdx::thin_vec::ThinVec;
1516
use syntax::{
1617
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
1718
AstNode,
@@ -33,8 +34,8 @@ use crate::{
3334
lower::LowerCtx,
3435
path::AssociatedTypeBinding,
3536
type_ref::{
36-
LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, TypesMap,
37-
TypesSourceMap,
37+
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
38+
TypesMap, TypesSourceMap,
3839
},
3940
visibility::RawVisibility,
4041
LocalLifetimeParamId, LocalTypeOrConstParamId,
@@ -463,20 +464,20 @@ impl<'a> Ctx<'a> {
463464
));
464465
match self_param.kind() {
465466
ast::SelfParamKind::Owned => self_type,
466-
ast::SelfParamKind::Ref => {
467-
body_ctx.alloc_type_ref_desugared(TypeRef::Reference(
468-
self_type,
469-
self_param.lifetime().as_ref().map(LifetimeRef::new),
470-
Mutability::Shared,
471-
))
472-
}
473-
ast::SelfParamKind::MutRef => {
474-
body_ctx.alloc_type_ref_desugared(TypeRef::Reference(
475-
self_type,
476-
self_param.lifetime().as_ref().map(LifetimeRef::new),
477-
Mutability::Mut,
478-
))
479-
}
467+
ast::SelfParamKind::Ref => body_ctx.alloc_type_ref_desugared(
468+
TypeRef::Reference(Box::new(RefType {
469+
ty: self_type,
470+
lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
471+
mutability: Mutability::Shared,
472+
})),
473+
),
474+
ast::SelfParamKind::MutRef => body_ctx.alloc_type_ref_desugared(
475+
TypeRef::Reference(Box::new(RefType {
476+
ty: self_type,
477+
lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
478+
mutability: Mutability::Mut,
479+
})),
480+
),
480481
}
481482
}
482483
};
@@ -511,7 +512,7 @@ impl<'a> Ctx<'a> {
511512
let ret_type = if func.async_token().is_some() {
512513
let future_impl = desugar_future_path(ret_type);
513514
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
514-
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(vec![ty_bound]))
515+
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
515516
} else {
516517
ret_type
517518
};

0 commit comments

Comments
 (0)