From 003ee0086ae424ec43ad14cd90af9cd5809a93c8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 4 Feb 2021 19:19:51 +0100 Subject: Intern `TypeRef`s in the containing `ItemTree` --- crates/hir_def/src/item_tree.rs | 54 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) (limited to 'crates/hir_def/src/item_tree.rs') diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 4bde67649..401556931 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -146,6 +146,7 @@ impl ItemTree { macro_defs, vis, generics, + type_refs, inner_items, } = &mut **data; @@ -169,6 +170,8 @@ impl ItemTree { vis.arena.shrink_to_fit(); generics.arena.shrink_to_fit(); + type_refs.arena.shrink_to_fit(); + type_refs.map.shrink_to_fit(); inner_items.shrink_to_fit(); } @@ -279,6 +282,32 @@ static EMPTY_GENERICS: GenericParams = GenericParams { where_predicates: Vec::new(), }; +/// `TypeRef` interner. +#[derive(Default, Debug, Eq, PartialEq)] +struct TypeRefStorage { + arena: Arena>, + map: FxHashMap, Idx>>, +} + +impl TypeRefStorage { + // Note: We lie about the `Idx` to hide the interner details. + + fn intern(&mut self, ty: TypeRef) -> Idx { + if let Some(id) = self.map.get(&ty) { + return Idx::from_raw(id.into_raw()); + } + + let ty = Arc::new(ty); + let idx = self.arena.alloc(ty.clone()); + self.map.insert(ty, idx); + Idx::from_raw(idx.into_raw()) + } + + fn lookup(&self, id: Idx) -> &TypeRef { + &self.arena[Idx::from_raw(id.into_raw())] + } +} + #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { imports: Arena, @@ -301,6 +330,7 @@ struct ItemTreeData { vis: ItemVisibilities, generics: GenericParamsStorage, + type_refs: TypeRefStorage, inner_items: FxHashMap, SmallVec<[ModItem; 1]>>, } @@ -489,6 +519,14 @@ impl Index for ItemTree { } } +impl Index> for ItemTree { + type Output = TypeRef; + + fn index(&self, id: Idx) -> &Self::Output { + self.data().type_refs.lookup(id) + } +} + impl Index> for ItemTree { type Output = N; fn index(&self, id: FileItemTreeId) -> &N { @@ -532,9 +570,9 @@ pub struct Function { /// Whether the function is located in an `extern` block (*not* whether it is an /// `extern "abi" fn`). pub is_extern: bool, - pub params: Box<[TypeRef]>, + pub params: Box<[Idx]>, pub is_varargs: bool, - pub ret_type: TypeRef, + pub ret_type: Idx, pub ast_id: FileAstId, } @@ -581,7 +619,7 @@ pub struct Const { /// const _: () = (); pub name: Option, pub visibility: RawVisibilityId, - pub type_ref: TypeRef, + pub type_ref: Idx, pub ast_id: FileAstId, } @@ -592,7 +630,7 @@ pub struct Static { pub mutable: bool, /// Whether the static is in an `extern` block. pub is_extern: bool, - pub type_ref: TypeRef, + pub type_ref: Idx, pub ast_id: FileAstId, } @@ -609,8 +647,8 @@ pub struct Trait { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { pub generic_params: GenericParamsId, - pub target_trait: Option, - pub target_type: TypeRef, + pub target_trait: Option>, + pub target_type: Idx, pub is_negative: bool, pub items: Box<[AssocItem]>, pub ast_id: FileAstId, @@ -623,7 +661,7 @@ pub struct TypeAlias { /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. pub bounds: Box<[TypeBound]>, pub generic_params: GenericParamsId, - pub type_ref: Option, + pub type_ref: Option>, pub is_extern: bool, pub ast_id: FileAstId, } @@ -806,6 +844,6 @@ pub enum Fields { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Field { pub name: Name, - pub type_ref: TypeRef, + pub type_ref: Idx, pub visibility: RawVisibilityId, } -- cgit v1.2.3