diff options
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 54 |
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)] | ||
287 | struct TypeRefStorage { | ||
288 | arena: Arena<Arc<TypeRef>>, | ||
289 | map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>, | ||
290 | } | ||
291 | |||
292 | impl 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)] |
283 | struct ItemTreeData { | 312 | struct 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 | ||
522 | impl 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 | |||
492 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 530 | impl<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)] |
610 | pub struct Impl { | 648 | pub 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)] |
807 | pub struct Field { | 845 | pub 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 | } |