diff options
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 42d9f0947..3233b1957 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | use test_utils::mark; | 28 | use test_utils::mark; |
29 | 29 | ||
30 | use crate::{ | 30 | use crate::{ |
@@ -80,6 +80,10 @@ impl ItemTree { | |||
80 | pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { | 80 | pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { |
81 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); | 81 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); |
82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { | 82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { |
83 | if node.kind() == SyntaxKind::ERROR { | ||
84 | // FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic | ||
85 | return Default::default(); | ||
86 | } | ||
83 | node | 87 | node |
84 | } else { | 88 | } else { |
85 | return Default::default(); | 89 | return Default::default(); |
@@ -142,6 +146,7 @@ impl ItemTree { | |||
142 | macro_defs, | 146 | macro_defs, |
143 | vis, | 147 | vis, |
144 | generics, | 148 | generics, |
149 | type_refs, | ||
145 | inner_items, | 150 | inner_items, |
146 | } = &mut **data; | 151 | } = &mut **data; |
147 | 152 | ||
@@ -165,6 +170,8 @@ impl ItemTree { | |||
165 | 170 | ||
166 | vis.arena.shrink_to_fit(); | 171 | vis.arena.shrink_to_fit(); |
167 | 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(); | ||
168 | 175 | ||
169 | inner_items.shrink_to_fit(); | 176 | inner_items.shrink_to_fit(); |
170 | } | 177 | } |
@@ -233,7 +240,7 @@ impl ItemVisibilities { | |||
233 | fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { | 240 | fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { |
234 | match &vis { | 241 | match &vis { |
235 | RawVisibility::Public => RawVisibilityId::PUB, | 242 | RawVisibility::Public => RawVisibilityId::PUB, |
236 | RawVisibility::Module(path) if path.segments.is_empty() => match &path.kind { | 243 | RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind { |
237 | PathKind::Super(0) => RawVisibilityId::PRIV, | 244 | PathKind::Super(0) => RawVisibilityId::PRIV, |
238 | PathKind::Crate => RawVisibilityId::PUB_CRATE, | 245 | PathKind::Crate => RawVisibilityId::PUB_CRATE, |
239 | _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), | 246 | _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), |
@@ -244,10 +251,8 @@ impl ItemVisibilities { | |||
244 | } | 251 | } |
245 | 252 | ||
246 | static VIS_PUB: RawVisibility = RawVisibility::Public; | 253 | static VIS_PUB: RawVisibility = RawVisibility::Public; |
247 | static VIS_PRIV: RawVisibility = | 254 | static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))); |
248 | RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() }); | 255 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); |
249 | static VIS_PUB_CRATE: RawVisibility = | ||
250 | RawVisibility::Module(ModPath { kind: PathKind::Crate, segments: Vec::new() }); | ||
251 | 256 | ||
252 | #[derive(Default, Debug, Eq, PartialEq)] | 257 | #[derive(Default, Debug, Eq, PartialEq)] |
253 | struct GenericParamsStorage { | 258 | struct GenericParamsStorage { |
@@ -275,6 +280,32 @@ static EMPTY_GENERICS: GenericParams = GenericParams { | |||
275 | where_predicates: Vec::new(), | 280 | where_predicates: Vec::new(), |
276 | }; | 281 | }; |
277 | 282 | ||
283 | /// `TypeRef` interner. | ||
284 | #[derive(Default, Debug, Eq, PartialEq)] | ||
285 | struct TypeRefStorage { | ||
286 | arena: Arena<Arc<TypeRef>>, | ||
287 | map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>, | ||
288 | } | ||
289 | |||
290 | impl TypeRefStorage { | ||
291 | // Note: We lie about the `Idx<TypeRef>` to hide the interner details. | ||
292 | |||
293 | fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> { | ||
294 | if let Some(id) = self.map.get(&ty) { | ||
295 | return Idx::from_raw(id.into_raw()); | ||
296 | } | ||
297 | |||
298 | let ty = Arc::new(ty); | ||
299 | let idx = self.arena.alloc(ty.clone()); | ||
300 | self.map.insert(ty, idx); | ||
301 | Idx::from_raw(idx.into_raw()) | ||
302 | } | ||
303 | |||
304 | fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef { | ||
305 | &self.arena[Idx::from_raw(id.into_raw())] | ||
306 | } | ||
307 | } | ||
308 | |||
278 | #[derive(Default, Debug, Eq, PartialEq)] | 309 | #[derive(Default, Debug, Eq, PartialEq)] |
279 | struct ItemTreeData { | 310 | struct ItemTreeData { |
280 | imports: Arena<Import>, | 311 | imports: Arena<Import>, |
@@ -297,6 +328,7 @@ struct ItemTreeData { | |||
297 | 328 | ||
298 | vis: ItemVisibilities, | 329 | vis: ItemVisibilities, |
299 | generics: GenericParamsStorage, | 330 | generics: GenericParamsStorage, |
331 | type_refs: TypeRefStorage, | ||
300 | 332 | ||
301 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 333 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
302 | } | 334 | } |
@@ -485,6 +517,14 @@ impl Index<GenericParamsId> for ItemTree { | |||
485 | } | 517 | } |
486 | } | 518 | } |
487 | 519 | ||
520 | impl Index<Idx<TypeRef>> for ItemTree { | ||
521 | type Output = TypeRef; | ||
522 | |||
523 | fn index(&self, id: Idx<TypeRef>) -> &Self::Output { | ||
524 | self.data().type_refs.lookup(id) | ||
525 | } | ||
526 | } | ||
527 | |||
488 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 528 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
489 | type Output = N; | 529 | type Output = N; |
490 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 530 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -528,9 +568,9 @@ pub struct Function { | |||
528 | /// Whether the function is located in an `extern` block (*not* whether it is an | 568 | /// Whether the function is located in an `extern` block (*not* whether it is an |
529 | /// `extern "abi" fn`). | 569 | /// `extern "abi" fn`). |
530 | pub is_extern: bool, | 570 | pub is_extern: bool, |
531 | pub params: Box<[TypeRef]>, | 571 | pub params: Box<[Idx<TypeRef>]>, |
532 | pub is_varargs: bool, | 572 | pub is_varargs: bool, |
533 | pub ret_type: TypeRef, | 573 | pub ret_type: Idx<TypeRef>, |
534 | pub ast_id: FileAstId<ast::Fn>, | 574 | pub ast_id: FileAstId<ast::Fn>, |
535 | } | 575 | } |
536 | 576 | ||
@@ -577,7 +617,7 @@ pub struct Const { | |||
577 | /// const _: () = (); | 617 | /// const _: () = (); |
578 | pub name: Option<Name>, | 618 | pub name: Option<Name>, |
579 | pub visibility: RawVisibilityId, | 619 | pub visibility: RawVisibilityId, |
580 | pub type_ref: TypeRef, | 620 | pub type_ref: Idx<TypeRef>, |
581 | pub ast_id: FileAstId<ast::Const>, | 621 | pub ast_id: FileAstId<ast::Const>, |
582 | } | 622 | } |
583 | 623 | ||
@@ -588,7 +628,7 @@ pub struct Static { | |||
588 | pub mutable: bool, | 628 | pub mutable: bool, |
589 | /// Whether the static is in an `extern` block. | 629 | /// Whether the static is in an `extern` block. |
590 | pub is_extern: bool, | 630 | pub is_extern: bool, |
591 | pub type_ref: TypeRef, | 631 | pub type_ref: Idx<TypeRef>, |
592 | pub ast_id: FileAstId<ast::Static>, | 632 | pub ast_id: FileAstId<ast::Static>, |
593 | } | 633 | } |
594 | 634 | ||
@@ -605,8 +645,8 @@ pub struct Trait { | |||
605 | #[derive(Debug, Clone, Eq, PartialEq)] | 645 | #[derive(Debug, Clone, Eq, PartialEq)] |
606 | pub struct Impl { | 646 | pub struct Impl { |
607 | pub generic_params: GenericParamsId, | 647 | pub generic_params: GenericParamsId, |
608 | pub target_trait: Option<TypeRef>, | 648 | pub target_trait: Option<Idx<TypeRef>>, |
609 | pub target_type: TypeRef, | 649 | pub target_type: Idx<TypeRef>, |
610 | pub is_negative: bool, | 650 | pub is_negative: bool, |
611 | pub items: Box<[AssocItem]>, | 651 | pub items: Box<[AssocItem]>, |
612 | pub ast_id: FileAstId<ast::Impl>, | 652 | pub ast_id: FileAstId<ast::Impl>, |
@@ -619,7 +659,7 @@ pub struct TypeAlias { | |||
619 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 659 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
620 | pub bounds: Box<[TypeBound]>, | 660 | pub bounds: Box<[TypeBound]>, |
621 | pub generic_params: GenericParamsId, | 661 | pub generic_params: GenericParamsId, |
622 | pub type_ref: Option<TypeRef>, | 662 | pub type_ref: Option<Idx<TypeRef>>, |
623 | pub is_extern: bool, | 663 | pub is_extern: bool, |
624 | pub ast_id: FileAstId<ast::TypeAlias>, | 664 | pub ast_id: FileAstId<ast::TypeAlias>, |
625 | } | 665 | } |
@@ -802,6 +842,6 @@ pub enum Fields { | |||
802 | #[derive(Debug, Clone, PartialEq, Eq)] | 842 | #[derive(Debug, Clone, PartialEq, Eq)] |
803 | pub struct Field { | 843 | pub struct Field { |
804 | pub name: Name, | 844 | pub name: Name, |
805 | pub type_ref: TypeRef, | 845 | pub type_ref: Idx<TypeRef>, |
806 | pub visibility: RawVisibilityId, | 846 | pub visibility: RawVisibilityId, |
807 | } | 847 | } |