aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/item_tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r--crates/hir_def/src/item_tree.rs54
1 files changed, 46 insertions, 8 deletions
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 {
146 macro_defs, 146 macro_defs,
147 vis, 147 vis,
148 generics, 148 generics,
149 type_refs,
149 inner_items, 150 inner_items,
150 } = &mut **data; 151 } = &mut **data;
151 152
@@ -169,6 +170,8 @@ impl ItemTree {
169 170
170 vis.arena.shrink_to_fit(); 171 vis.arena.shrink_to_fit();
171 generics.arena.shrink_to_fit(); 172 generics.arena.shrink_to_fit();
173 type_refs.arena.shrink_to_fit();
174 type_refs.map.shrink_to_fit();
172 175
173 inner_items.shrink_to_fit(); 176 inner_items.shrink_to_fit();
174 } 177 }
@@ -279,6 +282,32 @@ static EMPTY_GENERICS: GenericParams = GenericParams {
279 where_predicates: Vec::new(), 282 where_predicates: Vec::new(),
280}; 283};
281 284
285/// `TypeRef` interner.
286#[derive(Default, Debug, Eq, PartialEq)]
287struct TypeRefStorage {
288 arena: Arena<Arc<TypeRef>>,
289 map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>,
290}
291
292impl TypeRefStorage {
293 // Note: We lie about the `Idx<TypeRef>` to hide the interner details.
294
295 fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> {
296 if let Some(id) = self.map.get(&ty) {
297 return Idx::from_raw(id.into_raw());
298 }
299
300 let ty = Arc::new(ty);
301 let idx = self.arena.alloc(ty.clone());
302 self.map.insert(ty, idx);
303 Idx::from_raw(idx.into_raw())
304 }
305
306 fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef {
307 &self.arena[Idx::from_raw(id.into_raw())]
308 }
309}
310
282#[derive(Default, Debug, Eq, PartialEq)] 311#[derive(Default, Debug, Eq, PartialEq)]
283struct ItemTreeData { 312struct ItemTreeData {
284 imports: Arena<Import>, 313 imports: Arena<Import>,
@@ -301,6 +330,7 @@ struct ItemTreeData {
301 330
302 vis: ItemVisibilities, 331 vis: ItemVisibilities,
303 generics: GenericParamsStorage, 332 generics: GenericParamsStorage,
333 type_refs: TypeRefStorage,
304 334
305 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, 335 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
306} 336}
@@ -489,6 +519,14 @@ impl Index<GenericParamsId> for ItemTree {
489 } 519 }
490} 520}
491 521
522impl Index<Idx<TypeRef>> for ItemTree {
523 type Output = TypeRef;
524
525 fn index(&self, id: Idx<TypeRef>) -> &Self::Output {
526 self.data().type_refs.lookup(id)
527 }
528}
529
492impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { 530impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
493 type Output = N; 531 type Output = N;
494 fn index(&self, id: FileItemTreeId<N>) -> &N { 532 fn index(&self, id: FileItemTreeId<N>) -> &N {
@@ -532,9 +570,9 @@ pub struct Function {
532 /// Whether the function is located in an `extern` block (*not* whether it is an 570 /// Whether the function is located in an `extern` block (*not* whether it is an
533 /// `extern "abi" fn`). 571 /// `extern "abi" fn`).
534 pub is_extern: bool, 572 pub is_extern: bool,
535 pub params: Box<[TypeRef]>, 573 pub params: Box<[Idx<TypeRef>]>,
536 pub is_varargs: bool, 574 pub is_varargs: bool,
537 pub ret_type: TypeRef, 575 pub ret_type: Idx<TypeRef>,
538 pub ast_id: FileAstId<ast::Fn>, 576 pub ast_id: FileAstId<ast::Fn>,
539} 577}
540 578
@@ -581,7 +619,7 @@ pub struct Const {
581 /// const _: () = (); 619 /// const _: () = ();
582 pub name: Option<Name>, 620 pub name: Option<Name>,
583 pub visibility: RawVisibilityId, 621 pub visibility: RawVisibilityId,
584 pub type_ref: TypeRef, 622 pub type_ref: Idx<TypeRef>,
585 pub ast_id: FileAstId<ast::Const>, 623 pub ast_id: FileAstId<ast::Const>,
586} 624}
587 625
@@ -592,7 +630,7 @@ pub struct Static {
592 pub mutable: bool, 630 pub mutable: bool,
593 /// Whether the static is in an `extern` block. 631 /// Whether the static is in an `extern` block.
594 pub is_extern: bool, 632 pub is_extern: bool,
595 pub type_ref: TypeRef, 633 pub type_ref: Idx<TypeRef>,
596 pub ast_id: FileAstId<ast::Static>, 634 pub ast_id: FileAstId<ast::Static>,
597} 635}
598 636
@@ -609,8 +647,8 @@ pub struct Trait {
609#[derive(Debug, Clone, Eq, PartialEq)] 647#[derive(Debug, Clone, Eq, PartialEq)]
610pub struct Impl { 648pub struct Impl {
611 pub generic_params: GenericParamsId, 649 pub generic_params: GenericParamsId,
612 pub target_trait: Option<TypeRef>, 650 pub target_trait: Option<Idx<TypeRef>>,
613 pub target_type: TypeRef, 651 pub target_type: Idx<TypeRef>,
614 pub is_negative: bool, 652 pub is_negative: bool,
615 pub items: Box<[AssocItem]>, 653 pub items: Box<[AssocItem]>,
616 pub ast_id: FileAstId<ast::Impl>, 654 pub ast_id: FileAstId<ast::Impl>,
@@ -623,7 +661,7 @@ pub struct TypeAlias {
623 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. 661 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
624 pub bounds: Box<[TypeBound]>, 662 pub bounds: Box<[TypeBound]>,
625 pub generic_params: GenericParamsId, 663 pub generic_params: GenericParamsId,
626 pub type_ref: Option<TypeRef>, 664 pub type_ref: Option<Idx<TypeRef>>,
627 pub is_extern: bool, 665 pub is_extern: bool,
628 pub ast_id: FileAstId<ast::TypeAlias>, 666 pub ast_id: FileAstId<ast::TypeAlias>,
629} 667}
@@ -806,6 +844,6 @@ pub enum Fields {
806#[derive(Debug, Clone, PartialEq, Eq)] 844#[derive(Debug, Clone, PartialEq, Eq)]
807pub struct Field { 845pub struct Field {
808 pub name: Name, 846 pub name: Name,
809 pub type_ref: TypeRef, 847 pub type_ref: Idx<TypeRef>,
810 pub visibility: RawVisibilityId, 848 pub visibility: RawVisibilityId,
811} 849}