From 24e876b52ed76710593895bc37bb8ed303075193 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 5 Apr 2021 02:03:37 +0200 Subject: Intern more `TypeRef`s in generics Saves ~3 MB --- crates/hir_def/src/generics.rs | 16 +++++++++------- crates/hir_def/src/path.rs | 2 +- crates/hir_def/src/path/lower.rs | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 7c6cbff11..e02ac2c2f 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -18,6 +18,7 @@ use crate::{ child_by_source::ChildBySource, db::DefDatabase, dyn_map::DynMap, + intern::Interned, keys, src::{HasChildSource, HasSource}, type_ref::{LifetimeRef, TypeBound, TypeRef}, @@ -29,7 +30,7 @@ use crate::{ #[derive(Clone, PartialEq, Eq, Debug)] pub struct TypeParamData { pub name: Option, - pub default: Option, + pub default: Option>, pub provenance: TypeParamProvenance, } @@ -43,7 +44,7 @@ pub struct LifetimeParamData { #[derive(Clone, PartialEq, Eq, Debug)] pub struct ConstParamData { pub name: Name, - pub ty: TypeRef, + pub ty: Interned, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -75,7 +76,7 @@ pub enum WherePredicate { #[derive(Clone, PartialEq, Eq, Debug)] pub enum WherePredicateTypeTarget { - TypeRef(TypeRef), + TypeRef(Interned), /// For desugared where predicates that can directly refer to a type param. TypeParam(LocalTypeParamId), } @@ -256,7 +257,8 @@ impl GenericParams { for type_param in params.type_params() { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` - let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it)); + let default = + type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it))); let param = TypeParamData { name: Some(name.clone()), default, @@ -280,7 +282,7 @@ impl GenericParams { for const_param in params.const_params() { let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); - let param = ConstParamData { name, ty }; + let param = ConstParamData { name, ty: Interned::new(ty) }; let param_id = self.consts.alloc(param); sm.const_params.insert(param_id, const_param.clone()); } @@ -334,11 +336,11 @@ impl GenericParams { (Either::Left(type_ref), bound) => match hrtb_lifetimes { Some(hrtb_lifetimes) => WherePredicate::ForLifetime { lifetimes: hrtb_lifetimes.clone(), - target: WherePredicateTypeTarget::TypeRef(type_ref), + target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), bound, }, None => WherePredicate::TypeBound { - target: WherePredicateTypeTarget::TypeRef(type_ref), + target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), bound, }, }, diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index a3e83e2cf..f9c8328f0 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs @@ -122,7 +122,7 @@ impl ModPath { pub struct Path { /// Type based path like `::foo`. /// Note that paths like `::foo` are desugard to `Trait::::foo`. - type_anchor: Option>, + type_anchor: Option>, mod_path: Interned, /// Invariant: the same len as `self.mod_path.segments` generic_args: Vec>>, diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 28f6244da..7b29d9d4f 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs @@ -69,7 +69,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option match trait_ref { // ::foo None => { - type_anchor = Some(Box::new(self_type)); + type_anchor = Some(Interned::new(self_type)); kind = PathKind::Plain; } // >::Foo desugars to Trait::Foo -- cgit v1.2.3 From adcf18e27dc04b60fede859f3d6c22b99d4fd513 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 5 Apr 2021 03:32:43 +0200 Subject: Add `GenericParams::shrink_to_fit` Reduces memory usage by over 10 MB --- crates/hir_def/src/generics.rs | 9 +++++++++ crates/hir_def/src/item_tree/lower.rs | 1 + 2 files changed, 10 insertions(+) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index e02ac2c2f..d55c189d4 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -218,6 +218,7 @@ impl GenericParams { GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), }; + generics.shrink_to_fit(); (generics, InFile::new(file_id, sm)) } @@ -371,6 +372,14 @@ impl GenericParams { }); } + pub(crate) fn shrink_to_fit(&mut self) { + let Self { consts, lifetimes, types, where_predicates } = self; + consts.shrink_to_fit(); + lifetimes.shrink_to_fit(); + types.shrink_to_fit(); + where_predicates.shrink_to_fit(); + } + pub fn find_type_by_name(&self, name: &Name) -> Option { self.types .iter() diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index ab7ad8310..0c8112dda 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -739,6 +739,7 @@ impl Ctx { } } + generics.shrink_to_fit(); self.data().generics.alloc(generics) } -- cgit v1.2.3 From 7c0c713a102ee86ee32af115acba63a5c3b3a657 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 5 Apr 2021 03:50:10 +0200 Subject: Intern `GenericParams` Also share the same instance between `ItemTree` and `generic_params` query. --- crates/hir_def/src/db.rs | 3 +- crates/hir_def/src/generics.rs | 37 ++++++++++----------- crates/hir_def/src/intern.rs | 10 +++++- crates/hir_def/src/item_tree.rs | 61 ++++------------------------------- crates/hir_def/src/item_tree/lower.rs | 8 ++--- crates/hir_def/src/lib.rs | 2 +- crates/hir_def/src/resolver.rs | 3 +- 7 files changed, 44 insertions(+), 80 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 068b2ee38..9b7a213a1 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -13,6 +13,7 @@ use crate::{ data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, generics::GenericParams, import_map::ImportMap, + intern::Interned, item_tree::ItemTree, lang_item::{LangItemTarget, LangItems}, nameres::DefMap, @@ -113,7 +114,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { fn expr_scopes(&self, def: DefWithBodyId) -> Arc; #[salsa::invoke(GenericParams::generic_params_query)] - fn generic_params(&self, def: GenericDefId) -> Arc; + fn generic_params(&self, def: GenericDefId) -> Interned; #[salsa::invoke(Attrs::variants_attrs_query)] fn variants_attrs(&self, def: EnumId) -> Arc>; diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index d55c189d4..de5acced8 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -2,7 +2,6 @@ //! structs, impls, traits, etc. This module provides a common HIR for these //! generic parameters. See also the `Generics` type and the `generics_of` query //! in rustc. -use std::sync::Arc; use base_db::FileId; use either::Either; @@ -27,7 +26,7 @@ use crate::{ }; /// Data about a generic type parameter (to a function, struct, impl, ...). -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeParamData { pub name: Option, pub default: Option>, @@ -35,19 +34,19 @@ pub struct TypeParamData { } /// Data about a generic lifetime parameter (to a function, struct, impl, ...). -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct LifetimeParamData { pub name: Name, } /// Data about a generic const parameter (to a function, struct, impl, ...). -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct ConstParamData { pub name: Name, pub ty: Interned, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum TypeParamProvenance { TypeParamList, TraitSelf, @@ -55,7 +54,7 @@ pub enum TypeParamProvenance { } /// Data about the generic parameters of a function, struct, impl, etc. -#[derive(Clone, PartialEq, Eq, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] pub struct GenericParams { pub types: Arena, pub lifetimes: Arena, @@ -67,14 +66,14 @@ pub struct GenericParams { /// where clauses like `where T: Foo + Bar` are turned into multiple of these. /// It might still result in multiple actual predicates though, because of /// associated type bindings like `Iterator`. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum WherePredicate { TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, Lifetime { target: LifetimeRef, bound: LifetimeRef }, ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum WherePredicateTypeTarget { TypeRef(Interned), /// For desugared where predicates that can directly refer to a type param. @@ -92,7 +91,7 @@ impl GenericParams { pub(crate) fn generic_params_query( db: &dyn DefDatabase, def: GenericDefId, - ) -> Arc { + ) -> Interned { let _p = profile::span("generic_params_query"); let generics = match def { @@ -100,47 +99,49 @@ impl GenericParams { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::AdtId(AdtId::StructId(id)) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::AdtId(AdtId::EnumId(id)) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::AdtId(AdtId::UnionId(id)) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::TraitId(id) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::TypeAliasId(id) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() } GenericDefId::ImplId(id) => { let id = id.lookup(db).id; let tree = id.item_tree(db); let item = &tree[id.value]; - tree[item.generic_params].clone() + item.generic_params.clone() + } + GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { + Interned::new(GenericParams::default()) } - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(), }; - Arc::new(generics) + generics } fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile) { diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index d163f633f..2467e9299 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs @@ -14,6 +14,8 @@ use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue}; use once_cell::sync::OnceCell; use rustc_hash::FxHasher; +use crate::generics::GenericParams; + type InternMap = DashMap, (), BuildHasherDefault>; type Guard = RwLockWriteGuard<'static, HashMap, SharedValue<()>, BuildHasherDefault>>; @@ -194,4 +196,10 @@ macro_rules! impl_internable { )+ }; } -impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str); +impl_internable!( + crate::type_ref::TypeRef, + crate::type_ref::TraitRef, + crate::path::ModPath, + GenericParams, + str +); diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 739906778..240662486 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -58,13 +58,6 @@ impl fmt::Debug for RawVisibilityId { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct GenericParamsId(u32); - -impl GenericParamsId { - pub const EMPTY: Self = GenericParamsId(u32::max_value()); -} - /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { @@ -146,7 +139,6 @@ impl ItemTree { macro_rules, macro_defs, vis, - generics, inner_items, } = &mut **data; @@ -170,7 +162,6 @@ impl ItemTree { macro_defs.shrink_to_fit(); vis.arena.shrink_to_fit(); - generics.arena.shrink_to_fit(); inner_items.shrink_to_fit(); } @@ -241,32 +232,6 @@ static VIS_PUB: RawVisibility = RawVisibility::Public; static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))); static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); -#[derive(Default, Debug, Eq, PartialEq)] -struct GenericParamsStorage { - arena: Arena, -} - -impl GenericParamsStorage { - fn alloc(&mut self, params: GenericParams) -> GenericParamsId { - if params.types.is_empty() - && params.lifetimes.is_empty() - && params.consts.is_empty() - && params.where_predicates.is_empty() - { - return GenericParamsId::EMPTY; - } - - GenericParamsId(self.arena.alloc(params).into_raw().into()) - } -} - -static EMPTY_GENERICS: GenericParams = GenericParams { - types: Arena::new(), - lifetimes: Arena::new(), - consts: Arena::new(), - where_predicates: Vec::new(), -}; - #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { imports: Arena, @@ -289,7 +254,6 @@ struct ItemTreeData { macro_defs: Arena, vis: ItemVisibilities, - generics: GenericParamsStorage, inner_items: FxHashMap, SmallVec<[ModItem; 1]>>, } @@ -508,17 +472,6 @@ impl Index for ItemTree { } } -impl Index for ItemTree { - type Output = GenericParams; - - fn index(&self, index: GenericParamsId) -> &Self::Output { - match index { - GenericParamsId::EMPTY => &EMPTY_GENERICS, - _ => &self.data().generics.arena[Idx::from_raw(index.0.into())], - } - } -} - impl Index> for ItemTree { type Output = N; fn index(&self, id: FileItemTreeId) -> &N { @@ -555,7 +508,7 @@ pub struct ExternCrate { pub struct Function { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub abi: Option>, pub params: IdRange, pub ret_type: Interned, @@ -590,7 +543,7 @@ impl FnFlags { pub struct Struct { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub fields: Fields, pub ast_id: FileAstId, pub kind: StructDefKind, @@ -610,7 +563,7 @@ pub enum StructDefKind { pub struct Union { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub fields: Fields, pub ast_id: FileAstId, } @@ -619,7 +572,7 @@ pub struct Union { pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub variants: IdRange, pub ast_id: FileAstId, } @@ -648,7 +601,7 @@ pub struct Static { pub struct Trait { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub is_auto: bool, pub is_unsafe: bool, pub bounds: Box<[TypeBound]>, @@ -658,7 +611,7 @@ pub struct Trait { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub target_trait: Option>, pub self_ty: Interned, pub is_negative: bool, @@ -672,7 +625,7 @@ pub struct TypeAlias { pub visibility: RawVisibilityId, /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. pub bounds: Box<[TypeBound]>, - pub generic_params: GenericParamsId, + pub generic_params: Interned, pub type_ref: Option>, pub is_extern: bool, pub ast_id: FileAstId, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 0c8112dda..c5629af24 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -434,7 +434,7 @@ impl Ctx { let mut res = Function { name, visibility, - generic_params: GenericParamsId::EMPTY, + generic_params: Interned::new(GenericParams::default()), abi, params, ret_type: Interned::new(ret_type), @@ -682,7 +682,7 @@ impl Ctx { &mut self, owner: GenericsOwner<'_>, node: &impl ast::GenericParamsOwner, - ) -> GenericParamsId { + ) -> Interned { // Generics are part of item headers and may contain inner items we need to collect. if let Some(params) = node.generic_param_list() { self.collect_inner_items(params.syntax()); @@ -698,7 +698,7 @@ impl Ctx { &mut self, owner: GenericsOwner<'_>, node: &impl ast::GenericParamsOwner, - ) -> GenericParamsId { + ) -> Interned { let mut sm = &mut Default::default(); let mut generics = GenericParams::default(); match owner { @@ -740,7 +740,7 @@ impl Ctx { } generics.shrink_to_fit(); - self.data().generics.alloc(generics) + Interned::new(generics) } fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec { diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index f408e510a..be9a5e1a0 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -27,6 +27,7 @@ pub mod dyn_map; pub mod keys; pub mod item_tree; +pub mod intern; pub mod adt; pub mod data; @@ -49,7 +50,6 @@ pub mod import_map; #[cfg(test)] mod test_db; -mod intern; use std::{ hash::{Hash, Hasher}, diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a73585ee7..0391cc49b 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -14,6 +14,7 @@ use crate::{ db::DefDatabase, expr::{ExprId, LabelId, PatId}, generics::GenericParams, + intern::Interned, item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, nameres::DefMap, path::{ModPath, PathKind}, @@ -50,7 +51,7 @@ enum Scope { /// All the items and imported names of a module ModuleScope(ModuleItemMap), /// Brings the generic parameters of an item into scope - GenericParams { def: GenericDefId, params: Arc }, + GenericParams { def: GenericDefId, params: Interned }, /// Brings `Self` in `impl` block into scope ImplDefScope(ImplId), /// Brings `Self` in enum, struct and union definitions into scope -- cgit v1.2.3 From 6f1ee9a7f4987d5286e6d875f544ce11f02465f3 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 5 Apr 2021 04:27:57 +0200 Subject: simplify visibility.rs --- crates/hir_def/src/visibility.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/hir_def') diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 7d00a37c4..9908cd926 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs @@ -11,7 +11,7 @@ use crate::{ nameres::DefMap, path::{ModPath, PathKind}, resolver::HasResolver, - FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, + FunctionId, HasModule, LocalFieldId, ModuleId, VariantId, }; /// Visibility of an item, not yet resolved. @@ -25,7 +25,7 @@ pub enum RawVisibility { } impl RawVisibility { - pub(crate) const fn private() -> RawVisibility { + pub(crate) fn private() -> RawVisibility { RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) } @@ -217,6 +217,6 @@ pub(crate) fn field_visibilities_query( /// Resolve visibility of a function. pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { - let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); + let resolver = def.resolver(db); db.function_data(def).visibility.resolve(db, &resolver) } -- cgit v1.2.3