Skip to content

Commit

Permalink
Shrink TypeRef from 16 from 32 bytes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ChayimFriedman2 committed Oct 19, 2024
1 parent 8bbff79 commit be029b9
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 149 deletions.
101 changes: 52 additions & 49 deletions crates/hir-def/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use hir_expand::{
ExpandResult,
};
use la_arena::{Arena, RawIdx};
use stdx::impl_from;
use stdx::{
impl_from,
thin_vec::{EmptyOptimizedThinVec, ThinVec},
};
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
use triomphe::Arc;

Expand All @@ -22,7 +25,10 @@ use crate::{
lower::LowerCtx,
nameres::{DefMap, MacroSubNs},
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap},
type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
TypesSourceMap,
},
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
};
Expand Down Expand Up @@ -590,18 +596,18 @@ impl GenericParamsCollector {
self.where_predicates.push(predicate);
}

fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<TypeBound>>) {
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<ThinVec<TypeBound>>) {
for bounds in impl_bounds {
let param = TypeParamData {
name: None,
default: None,
provenance: TypeParamProvenance::ArgumentImplTrait,
};
let param_id = self.type_or_consts.alloc(param.into());
for bound in bounds {
for bound in &bounds {
self.where_predicates.push(WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
bound,
bound: bound.clone(),
});
}
}
Expand Down Expand Up @@ -725,46 +731,45 @@ fn copy_type_ref(
to_source_map: &mut TypesSourceMap,
) -> TypeRefId {
let result = match &from[type_ref] {
&TypeRef::Fn { ref params, is_varargs, is_unsafe, ref abi } => {
let params = params
.iter()
.map(|(name, param_type)| {
(
name.clone(),
copy_type_ref(*param_type, from, from_source_map, to, to_source_map),
)
})
.collect();
TypeRef::Fn { params, is_varargs, is_unsafe, abi: abi.clone() }
TypeRef::Fn(fn_) => {
let params = fn_.params().iter().map(|(name, param_type)| {
(name.clone(), copy_type_ref(*param_type, from, from_source_map, to, to_source_map))
});
TypeRef::Fn(FnType::new(fn_.is_varargs(), fn_.is_unsafe(), fn_.abi().clone(), params))
}
TypeRef::Tuple(types) => TypeRef::Tuple(
types
.iter()
.map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map))
.collect(),
),
TypeRef::Tuple(types) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
types.iter().map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map)),
)),
&TypeRef::RawPtr(type_ref, mutbl) => TypeRef::RawPtr(
copy_type_ref(type_ref, from, from_source_map, to, to_source_map),
mutbl,
),
TypeRef::Reference(type_ref, lifetime, mutbl) => TypeRef::Reference(
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map),
lifetime.clone(),
*mutbl,
),
TypeRef::Array(type_ref, len) => TypeRef::Array(
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map),
len.clone(),
),
TypeRef::Reference(ref_) => TypeRef::Reference(Box::new(RefType {
ty: copy_type_ref(ref_.ty, from, from_source_map, to, to_source_map),
lifetime: ref_.lifetime.clone(),
mutability: ref_.mutability,
})),
TypeRef::Array(array) => TypeRef::Array(Box::new(ArrayType {
ty: copy_type_ref(array.ty, from, from_source_map, to, to_source_map),
len: array.len.clone(),
})),
&TypeRef::Slice(type_ref) => {
TypeRef::Slice(copy_type_ref(type_ref, from, from_source_map, to, to_source_map))
}
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(),
),
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(),
),
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(ThinVec::from_iter(copy_type_bounds(
bounds,
from,
from_source_map,
to,
to_source_map,
))),
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(ThinVec::from_iter(copy_type_bounds(
bounds,
from,
from_source_map,
to,
to_source_map,
))),
TypeRef::Path(path) => {
TypeRef::Path(copy_path(path, from, from_source_map, to, to_source_map))
}
Expand Down Expand Up @@ -833,7 +838,8 @@ fn copy_generic_args(
copy_type_ref(type_ref, from, from_source_map, to, to_source_map)
});
let bounds =
copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map);
copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map)
.collect();
AssociatedTypeBinding { name, args, type_ref, bounds }
})
.collect();
Expand All @@ -846,17 +852,14 @@ fn copy_generic_args(
})
}

fn copy_type_bounds(
bounds: &[TypeBound],
from: &TypesMap,
from_source_map: &TypesSourceMap,
to: &mut TypesMap,
to_source_map: &mut TypesSourceMap,
) -> Box<[TypeBound]> {
bounds
.iter()
.map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
.collect()
fn copy_type_bounds<'a>(
bounds: &'a [TypeBound],
from: &'a TypesMap,
from_source_map: &'a TypesSourceMap,
to: &'a mut TypesMap,
to_source_map: &'a mut TypesSourceMap,
) -> impl stdx::thin_vec::TrustedLen<Item = TypeBound> + 'a {
bounds.iter().map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
}

fn copy_type_bound(
Expand Down
87 changes: 53 additions & 34 deletions crates/hir-def/src/hir/type_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use hir_expand::{
use intern::{sym, Symbol};
use la_arena::{Arena, ArenaMap, Idx};
use span::Edition;
use stdx::thin_vec::{thin_vec_with_header_struct, EmptyOptimizedThinVec, ThinVec};
use syntax::{
ast::{self, HasGenericArgs, HasName, IsString},
AstPtr,
Expand Down Expand Up @@ -108,31 +109,50 @@ impl TraitRef {
}
}

thin_vec_with_header_struct! {
pub new(pub(crate)) struct FnType, FnTypeHeader {
pub params: [(Option<Name>, TypeRefId)],
pub is_varargs: bool,
pub is_unsafe: bool,
pub abi: Option<Symbol>; ref,
}
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ArrayType {
pub ty: TypeRefId,
// FIXME: This should be Ast<ConstArg>
pub len: ConstRef,
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct RefType {
pub ty: TypeRefId,
pub lifetime: Option<LifetimeRef>,
pub mutability: Mutability,
}

/// Compare ty::Ty
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum TypeRef {
Never,
Placeholder,
Tuple(Vec<TypeRefId>),
Tuple(EmptyOptimizedThinVec<TypeRefId>),
Path(Path),
RawPtr(TypeRefId, Mutability),
Reference(TypeRefId, Option<LifetimeRef>, Mutability),
// FIXME: This should be Array(TypeRefId, Ast<ConstArg>),
Array(TypeRefId, ConstRef),
Reference(Box<RefType>),
Array(Box<ArrayType>),
Slice(TypeRefId),
/// A fn pointer. Last element of the vector is the return type.
Fn {
params: Box<[(Option<Name>, TypeRefId)]>,
is_varargs: bool,
is_unsafe: bool,
abi: Option<Symbol>,
},
ImplTrait(Vec<TypeBound>),
DynTrait(Vec<TypeBound>),
Fn(FnType),
ImplTrait(ThinVec<TypeBound>),
DynTrait(ThinVec<TypeBound>),
Macro(AstId<ast::MacroCall>),
Error,
}

const _: () = assert!(size_of::<TypeRef>() == 16);

pub type TypeRefId = Idx<TypeRef>;

#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
Expand Down Expand Up @@ -212,9 +232,9 @@ impl TypeRef {
pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId {
let ty = match &node {
ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
ast::Type::TupleType(inner) => {
TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
}
ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
Vec::from_iter(inner.fields().map(|it| TypeRef::from_ast(ctx, it))),
)),
ast::Type::NeverType(..) => TypeRef::Never,
ast::Type::PathType(inner) => {
// FIXME: Use `Path::from_src`
Expand All @@ -231,22 +251,25 @@ impl TypeRef {
}
ast::Type::ArrayType(inner) => {
let len = ConstRef::from_const_arg(ctx, inner.const_arg());
TypeRef::Array(TypeRef::from_ast_opt(ctx, inner.ty()), len)
TypeRef::Array(Box::new(ArrayType {
ty: TypeRef::from_ast_opt(ctx, inner.ty()),
len,
}))
}
ast::Type::SliceType(inner) => TypeRef::Slice(TypeRef::from_ast_opt(ctx, inner.ty())),
ast::Type::RefType(inner) => {
let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty());
let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt));
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
TypeRef::Reference(inner_ty, lifetime, mutability)
TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
}
ast::Type::InferType(_inner) => TypeRef::Placeholder,
ast::Type::FnPtrType(inner) => {
let ret_ty = inner
.ret_type()
.and_then(|rt| rt.ty())
.map(|it| TypeRef::from_ast(ctx, it))
.unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::Tuple(Vec::new())));
.unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::unit()));
let mut is_varargs = false;
let mut params = if let Some(pl) = inner.param_list() {
if let Some(param) = pl.params().last() {
Expand Down Expand Up @@ -278,12 +301,7 @@ impl TypeRef {

let abi = inner.abi().map(lower_abi);
params.push((None, ret_ty));
TypeRef::Fn {
params: params.into(),
is_varargs,
is_unsafe: inner.unsafe_token().is_some(),
abi,
}
TypeRef::Fn(FnType::new(is_varargs, inner.unsafe_token().is_some(), abi, params))
}
// for types are close enough for our purposes to the inner type for now...
ast::Type::ForType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
Expand Down Expand Up @@ -315,7 +333,7 @@ impl TypeRef {
}

pub(crate) fn unit() -> TypeRef {
TypeRef::Tuple(Vec::new())
TypeRef::Tuple(EmptyOptimizedThinVec::empty())
}

pub fn walk(this: TypeRefId, map: &TypesMap, f: &mut impl FnMut(&TypeRef)) {
Expand All @@ -325,14 +343,13 @@ impl TypeRef {
let type_ref = &map[type_ref];
f(type_ref);
match type_ref {
TypeRef::Fn { params, is_varargs: _, is_unsafe: _, abi: _ } => {
params.iter().for_each(|&(_, param_type)| go(param_type, f, map))
TypeRef::Fn(fn_) => {
fn_.params().iter().for_each(|&(_, param_type)| go(param_type, f, map))
}
TypeRef::Tuple(types) => types.iter().for_each(|&t| go(t, f, map)),
TypeRef::RawPtr(type_ref, _)
| TypeRef::Reference(type_ref, ..)
| TypeRef::Array(type_ref, _)
| TypeRef::Slice(type_ref) => go(*type_ref, f, map),
TypeRef::RawPtr(type_ref, _) | TypeRef::Slice(type_ref) => go(*type_ref, f, map),
TypeRef::Reference(it) => go(it.ty, f, map),
TypeRef::Array(it) => go(it.ty, f, map),
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
for bound in bounds {
match bound {
Expand Down Expand Up @@ -384,11 +401,13 @@ impl TypeRef {
pub(crate) fn type_bounds_from_ast(
lower_ctx: &LowerCtx<'_>,
type_bounds_opt: Option<ast::TypeBoundList>,
) -> Vec<TypeBound> {
) -> ThinVec<TypeBound> {
if let Some(type_bounds) = type_bounds_opt {
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
ThinVec::from_iter(Vec::from_iter(
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)),
))
} else {
vec![]
ThinVec::from_iter([])
}
}

Expand Down
35 changes: 18 additions & 17 deletions crates/hir-def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use intern::{sym, Symbol};
use la_arena::Arena;
use rustc_hash::FxHashMap;
use span::{AstIdMap, SyntaxContextId};
use stdx::thin_vec::ThinVec;
use syntax::{
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
AstNode,
Expand All @@ -33,8 +34,8 @@ use crate::{
lower::LowerCtx,
path::AssociatedTypeBinding,
type_ref::{
LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, TypesMap,
TypesSourceMap,
LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
TypesMap, TypesSourceMap,
},
visibility::RawVisibility,
LocalLifetimeParamId, LocalTypeOrConstParamId,
Expand Down Expand Up @@ -463,20 +464,20 @@ impl<'a> Ctx<'a> {
));
match self_param.kind() {
ast::SelfParamKind::Owned => self_type,
ast::SelfParamKind::Ref => {
body_ctx.alloc_type_ref_desugared(TypeRef::Reference(
self_type,
self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Shared,
))
}
ast::SelfParamKind::MutRef => {
body_ctx.alloc_type_ref_desugared(TypeRef::Reference(
self_type,
self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Mut,
))
}
ast::SelfParamKind::Ref => body_ctx.alloc_type_ref_desugared(
TypeRef::Reference(Box::new(RefType {
ty: self_type,
lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
mutability: Mutability::Shared,
})),
),
ast::SelfParamKind::MutRef => body_ctx.alloc_type_ref_desugared(
TypeRef::Reference(Box::new(RefType {
ty: self_type,
lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
mutability: Mutability::Mut,
})),
),
}
}
};
Expand Down Expand Up @@ -511,7 +512,7 @@ impl<'a> Ctx<'a> {
let ret_type = if func.async_token().is_some() {
let future_impl = desugar_future_path(ret_type);
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(vec![ty_bound]))
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
} else {
ret_type
};
Expand Down
Loading

0 comments on commit be029b9

Please sign in to comment.