aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/db.rs23
-rw-r--r--crates/ra_hir_def/src/imp.rs71
-rw-r--r--crates/ra_hir_def/src/lib.rs36
-rw-r--r--crates/ra_hir_def/src/nameres.rs7
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs29
6 files changed, 156 insertions, 21 deletions
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 40b5920d9..348aca07f 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -8,30 +8,32 @@ use ra_syntax::ast;
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 body::{scope::ExprScopes, Body, BodySourceMap}, 10 body::{scope::ExprScopes, Body, BodySourceMap},
11 imp::ImplData,
11 nameres::{ 12 nameres::{
12 raw::{ImportSourceMap, RawItems}, 13 raw::{ImportSourceMap, RawItems},
13 CrateDefMap, 14 CrateDefMap,
14 }, 15 },
15 DefWithBodyId, EnumId, StructOrUnionId, 16 DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId,
16}; 17};
17 18
18#[salsa::query_group(InternDatabaseStorage)] 19#[salsa::query_group(InternDatabaseStorage)]
19pub trait InternDatabase: SourceDatabase { 20pub trait InternDatabase: SourceDatabase {
20 #[salsa::interned] 21 #[salsa::interned]
21 fn intern_function(&self, loc: crate::ItemLoc<ast::FnDef>) -> crate::FunctionId; 22 fn intern_function(&self, loc: ItemLoc<ast::FnDef>) -> crate::FunctionId;
22 #[salsa::interned] 23 #[salsa::interned]
23 fn intern_struct_or_union(&self, loc: crate::ItemLoc<ast::StructDef>) 24 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
24 -> crate::StructOrUnionId;
25 #[salsa::interned] 25 #[salsa::interned]
26 fn intern_enum(&self, loc: crate::ItemLoc<ast::EnumDef>) -> crate::EnumId; 26 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId;
27 #[salsa::interned] 27 #[salsa::interned]
28 fn intern_const(&self, loc: crate::ItemLoc<ast::ConstDef>) -> crate::ConstId; 28 fn intern_const(&self, loc: ItemLoc<ast::ConstDef>) -> crate::ConstId;
29 #[salsa::interned] 29 #[salsa::interned]
30 fn intern_static(&self, loc: crate::ItemLoc<ast::StaticDef>) -> crate::StaticId; 30 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId;
31 #[salsa::interned] 31 #[salsa::interned]
32 fn intern_trait(&self, loc: crate::ItemLoc<ast::TraitDef>) -> crate::TraitId; 32 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId;
33 #[salsa::interned] 33 #[salsa::interned]
34 fn intern_type_alias(&self, loc: crate::ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId; 34 fn intern_type_alias(&self, loc: ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId;
35 #[salsa::interned]
36 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId;
35} 37}
36 38
37#[salsa::query_group(DefDatabase2Storage)] 39#[salsa::query_group(DefDatabase2Storage)]
@@ -54,6 +56,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
54 #[salsa::invoke(EnumData::enum_data_query)] 56 #[salsa::invoke(EnumData::enum_data_query)]
55 fn enum_data(&self, e: EnumId) -> Arc<EnumData>; 57 fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
56 58
59 #[salsa::invoke(ImplData::impl_data_query)]
60 fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
61
57 #[salsa::invoke(Body::body_with_source_map_query)] 62 #[salsa::invoke(Body::body_with_source_map_query)]
58 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 63 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
59 64
diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/imp.rs
new file mode 100644
index 000000000..717991c40
--- /dev/null
+++ b/crates/ra_hir_def/src/imp.rs
@@ -0,0 +1,71 @@
1//! Defines hir-level representation of impls.
2//!
3//! The handling is similar, but is not quite the same as for other items,
4//! because `impl`s don't have names.
5
6use std::sync::Arc;
7
8use ra_syntax::ast;
9
10use crate::{
11 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId,
12 LocationCtx, TypeAliasId,
13};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct ImplData {
17 target_trait: Option<TypeRef>,
18 target_type: TypeRef,
19 items: Vec<AssocItemId>,
20 negative: bool,
21}
22
23impl ImplData {
24 pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
25 let src = id.source(db);
26 let items = db.ast_id_map(src.file_id);
27
28 let target_trait = src.ast.target_trait().map(TypeRef::from_ast);
29 let target_type = TypeRef::from_ast_opt(src.ast.target_type());
30 let negative = src.ast.is_negative();
31
32 let items = if let Some(item_list) = src.ast.item_list() {
33 let ctx = LocationCtx::new(db, id.module(db), src.file_id);
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => {
38 FunctionId::from_ast_id(ctx, items.ast_id(&it)).into()
39 }
40 ast::ImplItem::ConstDef(it) => {
41 ConstId::from_ast_id(ctx, items.ast_id(&it)).into()
42 }
43 ast::ImplItem::TypeAliasDef(it) => {
44 TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into()
45 }
46 })
47 .collect()
48 } else {
49 Vec::new()
50 };
51
52 let res = ImplData { target_trait, target_type, items, negative };
53 Arc::new(res)
54 }
55
56 pub fn target_trait(&self) -> Option<&TypeRef> {
57 self.target_trait.as_ref()
58 }
59
60 pub fn target_type(&self) -> &TypeRef {
61 &self.target_type
62 }
63
64 pub fn items(&self) -> &[AssocItemId] {
65 &self.items
66 }
67
68 pub fn is_negative(&self) -> bool {
69 self.negative
70 }
71}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 3fab7965c..a240a10b8 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,6 +13,7 @@ pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod imp;
16pub mod diagnostics; 17pub mod diagnostics;
17pub mod expr; 18pub mod expr;
18pub mod body; 19pub mod body;
@@ -77,14 +78,13 @@ impl ModuleSource {
77 } 78 }
78 } 79 }
79 80
80 pub fn from_child_node( 81 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
81 db: &impl db::DefDatabase2, 82 if let Some(m) =
82 file_id: FileId, 83 child.ast.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
83 child: &SyntaxNode, 84 {
84 ) -> ModuleSource {
85 if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
86 ModuleSource::Module(m) 85 ModuleSource::Module(m)
87 } else { 86 } else {
87 let file_id = child.file_id.original_file(db);
88 let source_file = db.parse(file_id).tree(); 88 let source_file = db.parse(file_id).tree();
89 ModuleSource::SourceFile(source_file) 89 ModuleSource::SourceFile(source_file)
90 } 90 }
@@ -321,6 +321,18 @@ impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
321 } 321 }
322} 322}
323 323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
325pub struct ImplId(salsa::InternId);
326impl_intern_key!(ImplId);
327impl AstItemDef<ast::ImplBlock> for ImplId {
328 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ImplBlock>) -> Self {
329 db.intern_impl(loc)
330 }
331 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ImplBlock> {
332 db.lookup_intern_impl(self)
333 }
334}
335
324macro_rules! impl_froms { 336macro_rules! impl_froms {
325 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 337 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
326 $( 338 $(
@@ -384,3 +396,15 @@ pub enum DefWithBodyId {
384} 396}
385 397
386impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); 398impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId);
399
400#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
401pub enum AssocItemId {
402 FunctionId(FunctionId),
403 ConstId(ConstId),
404 TypeAliasId(TypeAliasId),
405}
406// FIXME: not every function, ... is actually an assoc item. maybe we should make
407// sure that you can only turn actual assoc items into AssocItemIds. This would
408// require not implementing From, and instead having some checked way of
409// casting them, and somehow making the constructors private, which would be annoying.
410impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId);
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index dfcec6443..e5b073a0f 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -73,7 +73,7 @@ use crate::{
73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId, 73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId,
74 }, 74 },
75 path::Path, 75 path::Path,
76 AstId, CrateModuleId, FunctionId, ModuleDefId, ModuleId, TraitId, 76 AstId, CrateModuleId, FunctionId, ImplId, ModuleDefId, ModuleId, TraitId,
77}; 77};
78 78
79/// Contains all top-level defs from a macro-expanded crate 79/// Contains all top-level defs from a macro-expanded crate
@@ -122,14 +122,15 @@ pub struct ModuleData {
122 /// 122 ///
123 /// Note that non-inline modules, by definition, live inside non-macro file. 123 /// Note that non-inline modules, by definition, live inside non-macro file.
124 pub definition: Option<FileId>, 124 pub definition: Option<FileId>,
125 pub impls: Vec<ImplId>,
125} 126}
126 127
127#[derive(Default, Debug, PartialEq, Eq, Clone)] 128#[derive(Default, Debug, PartialEq, Eq)]
128pub(crate) struct Declarations { 129pub(crate) struct Declarations {
129 fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>, 130 fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
130} 131}
131 132
132#[derive(Debug, Default, PartialEq, Eq, Clone)] 133#[derive(Debug, Default, PartialEq, Eq)]
133pub struct ModuleScope { 134pub struct ModuleScope {
134 items: FxHashMap<Name, Resolution>, 135 items: FxHashMap<Name, Resolution>,
135 /// Macros visable in current module in legacy textual scope 136 /// Macros visable in current module in legacy textual scope
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 5c899aff3..c9ccb9023 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -19,7 +19,7 @@ use crate::{
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, 22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, ImplId,
23 LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, 23 LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId,
24 UnionId, 24 UnionId,
25}; 25};
@@ -571,6 +571,15 @@ where
571 .push((self.module_id, import_id, self.raw_items[import_id].clone())), 571 .push((self.module_id, import_id, self.raw_items[import_id].clone())),
572 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), 572 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]),
573 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 573 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
574 raw::RawItemKind::Impl(imp) => {
575 let module = ModuleId {
576 krate: self.def_collector.def_map.krate,
577 module_id: self.module_id,
578 };
579 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
580 let imp_id = ImplId::from_ast_id(ctx, self.raw_items[imp].ast_id);
581 self.def_collector.def_map.modules[self.module_id].impls.push(imp_id)
582 }
574 } 583 }
575 } 584 }
576 } 585 }
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index f52002bc0..a0a2c7273 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -28,6 +28,7 @@ pub struct RawItems {
28 imports: Arena<ImportId, ImportData>, 28 imports: Arena<ImportId, ImportData>,
29 defs: Arena<Def, DefData>, 29 defs: Arena<Def, DefData>,
30 macros: Arena<Macro, MacroData>, 30 macros: Arena<Macro, MacroData>,
31 impls: Arena<Impl, ImplData>,
31 /// items for top-level module 32 /// items for top-level module
32 items: Vec<RawItem>, 33 items: Vec<RawItem>,
33} 34}
@@ -121,6 +122,13 @@ impl Index<Macro> for RawItems {
121 } 122 }
122} 123}
123 124
125impl Index<Impl> for RawItems {
126 type Output = ImplData;
127 fn index(&self, idx: Impl) -> &ImplData {
128 &self.impls[idx]
129 }
130}
131
124// Avoid heap allocation on items without attributes. 132// Avoid heap allocation on items without attributes.
125type Attrs = Option<Arc<[Attr]>>; 133type Attrs = Option<Arc<[Attr]>>;
126 134
@@ -142,6 +150,7 @@ pub(super) enum RawItemKind {
142 Import(ImportId), 150 Import(ImportId),
143 Def(Def), 151 Def(Def),
144 Macro(Macro), 152 Macro(Macro),
153 Impl(Impl),
145} 154}
146 155
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -203,6 +212,15 @@ pub(super) struct MacroData {
203 pub(super) builtin: bool, 212 pub(super) builtin: bool,
204} 213}
205 214
215#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
216pub(super) struct Impl(RawId);
217impl_arena_id!(Impl);
218
219#[derive(Debug, PartialEq, Eq)]
220pub(super) struct ImplData {
221 pub(super) ast_id: FileAstId<ast::ImplBlock>,
222}
223
206struct RawItemsCollector { 224struct RawItemsCollector {
207 raw_items: RawItems, 225 raw_items: RawItems,
208 source_ast_id_map: Arc<AstIdMap>, 226 source_ast_id_map: Arc<AstIdMap>,
@@ -236,8 +254,8 @@ impl RawItemsCollector {
236 self.add_extern_crate_item(current_module, extern_crate); 254 self.add_extern_crate_item(current_module, extern_crate);
237 return; 255 return;
238 } 256 }
239 ast::ModuleItem::ImplBlock(_) => { 257 ast::ModuleItem::ImplBlock(it) => {
240 // impls don't participate in name resolution 258 self.add_impl(current_module, it);
241 return; 259 return;
242 } 260 }
243 ast::ModuleItem::StructDef(it) => { 261 ast::ModuleItem::StructDef(it) => {
@@ -376,6 +394,13 @@ impl RawItemsCollector {
376 self.push_item(current_module, attrs, RawItemKind::Macro(m)); 394 self.push_item(current_module, attrs, RawItemKind::Macro(m));
377 } 395 }
378 396
397 fn add_impl(&mut self, current_module: Option<Module>, imp: ast::ImplBlock) {
398 let attrs = self.parse_attrs(&imp);
399 let ast_id = self.source_ast_id_map.ast_id(&imp);
400 let imp = self.raw_items.impls.alloc(ImplData { ast_id });
401 self.push_item(current_module, attrs, RawItemKind::Impl(imp))
402 }
403
379 fn push_import( 404 fn push_import(
380 &mut self, 405 &mut self,
381 current_module: Option<Module>, 406 current_module: Option<Module>,