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.rs68
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};
24use profile::Count; 24use profile::Count;
25use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
26use smallvec::SmallVec; 26use smallvec::SmallVec;
27use syntax::{ast, match_ast}; 27use syntax::{ast, match_ast, SyntaxKind};
28use test_utils::mark; 28use test_utils::mark;
29 29
30use crate::{ 30use 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
246static VIS_PUB: RawVisibility = RawVisibility::Public; 253static VIS_PUB: RawVisibility = RawVisibility::Public;
247static VIS_PRIV: RawVisibility = 254static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)));
248 RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() }); 255static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
249static 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)]
253struct GenericParamsStorage { 258struct 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)]
285struct TypeRefStorage {
286 arena: Arena<Arc<TypeRef>>,
287 map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>,
288}
289
290impl 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)]
279struct ItemTreeData { 310struct 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
520impl 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
488impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { 528impl<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)]
606pub struct Impl { 646pub 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)]
803pub struct Field { 843pub 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}