aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs25
-rw-r--r--crates/ra_hir/src/db.rs20
-rw-r--r--crates/ra_hir/src/from_id.rs15
-rw-r--r--crates/ra_hir/src/from_source.rs10
-rw-r--r--crates/ra_hir/src/impl_block.rs260
-rw-r--r--crates/ra_hir/src/lang_item.rs2
-rw-r--r--crates/ra_hir/src/lib.rs6
-rw-r--r--crates/ra_hir/src/resolve.rs5
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs80
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs6
-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.rs25
-rw-r--r--crates/ra_hir_def/src/nameres.rs3
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs29
-rw-r--r--crates/ra_ide_api/src/change.rs4
-rw-r--r--crates/ra_ide_api/src/references/classify.rs16
18 files changed, 241 insertions, 370 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 078bd8609..731cc1fff 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -11,7 +11,7 @@ use hir_def::{
11 body::scope::ExprScopes, 11 body::scope::ExprScopes,
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 type_ref::{Mutability, TypeRef}, 13 type_ref::{Mutability, TypeRef},
14 CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, 14 CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId,
15}; 15};
16use hir_expand::{ 16use hir_expand::{
17 diagnostics::DiagnosticSink, 17 diagnostics::DiagnosticSink,
@@ -29,7 +29,6 @@ use crate::{
29 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, 29 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
30 TypeAliasId, 30 TypeAliasId,
31 }, 31 },
32 impl_block::ImplBlock,
33 resolve::{Resolver, Scope, TypeNs}, 32 resolve::{Resolver, Scope, TypeNs},
34 traits::TraitData, 33 traits::TraitData,
35 ty::{InferenceResult, Namespace, TraitRef}, 34 ty::{InferenceResult, Namespace, TraitRef},
@@ -243,12 +242,8 @@ impl Module {
243 } 242 }
244 243
245 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { 244 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
246 let module_impl_blocks = db.impls_in_module(self); 245 let def_map = db.crate_def_map(self.id.krate);
247 module_impl_blocks 246 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect()
248 .impls
249 .iter()
250 .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id))
251 .collect()
252 } 247 }
253 248
254 fn with_module_id(self, module_id: CrateModuleId) -> Module { 249 fn with_module_id(self, module_id: CrateModuleId) -> Module {
@@ -693,8 +688,7 @@ impl Function {
693 688
694 /// The containing impl block, if this is a method. 689 /// The containing impl block, if this is a method.
695 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 690 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
696 let module_impls = db.impls_in_module(self.module(db)); 691 ImplBlock::containing(db, self.into())
697 ImplBlock::containing(module_impls, self.into())
698 } 692 }
699 693
700 /// The containing trait, if this is a trait method definition. 694 /// The containing trait, if this is a trait method definition.
@@ -759,8 +753,7 @@ impl Const {
759 753
760 /// The containing impl block, if this is a method. 754 /// The containing impl block, if this is a method.
761 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 755 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
762 let module_impls = db.impls_in_module(self.module(db)); 756 ImplBlock::containing(db, self.into())
763 ImplBlock::containing(module_impls, self.into())
764 } 757 }
765 758
766 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 759 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
@@ -973,8 +966,7 @@ impl TypeAlias {
973 966
974 /// The containing impl block, if this is a method. 967 /// The containing impl block, if this is a method.
975 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 968 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
976 let module_impls = db.impls_in_module(self.module(db)); 969 ImplBlock::containing(db, self.into())
977 ImplBlock::containing(module_impls, self.into())
978 } 970 }
979 971
980 /// The containing trait, if this is a trait method definition. 972 /// The containing trait, if this is a trait method definition.
@@ -1137,3 +1129,8 @@ pub struct GenericParam {
1137 pub(crate) parent: GenericDef, 1129 pub(crate) parent: GenericDef,
1138 pub(crate) idx: u32, 1130 pub(crate) idx: u32,
1139} 1131}
1132
1133#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1134pub struct ImplBlock {
1135 pub(crate) id: ImplId,
1136}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index c60029c01..276b0774f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -10,7 +10,6 @@ use crate::{
10 debug::HirDebugDatabase, 10 debug::HirDebugDatabase,
11 generics::{GenericDef, GenericParams}, 11 generics::{GenericDef, GenericParams},
12 ids, 12 ids,
13 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
14 lang_item::{LangItemTarget, LangItems}, 13 lang_item::{LangItemTarget, LangItems},
15 traits::TraitData, 14 traits::TraitData,
16 ty::{ 15 ty::{
@@ -18,14 +17,14 @@ use crate::{
18 InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, 17 InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor,
19 }, 18 },
20 type_alias::TypeAliasData, 19 type_alias::TypeAliasData,
21 Const, ConstData, Crate, DefWithBody, FnData, Function, Module, Static, StructField, Trait, 20 Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField,
22 TypeAlias, 21 Trait, TypeAlias,
23}; 22};
24 23
25pub use hir_def::db::{ 24pub use hir_def::db::{
26 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, 25 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
27 EnumDataQuery, ExprScopesQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, 26 EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
28 RawItemsWithSourceMapQuery, StructDataQuery, 27 RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
29}; 28};
30pub use hir_expand::db::{ 29pub use hir_expand::db::{
31 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -42,15 +41,6 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
42 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] 41 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
43 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; 42 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
44 43
45 #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)]
46 fn impls_in_module_with_source_map(
47 &self,
48 module: Module,
49 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>);
50
51 #[salsa::invoke(ModuleImplBlocks::impls_in_module_query)]
52 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
53
54 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] 44 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
55 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; 45 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
56 46
@@ -128,7 +118,7 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
128 #[salsa::interned] 118 #[salsa::interned]
129 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; 119 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
130 #[salsa::interned] 120 #[salsa::interned]
131 fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId; 121 fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId;
132 122
133 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] 123 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
134 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; 124 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index 9633ef586..f2203e995 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -3,9 +3,9 @@
3//! It's unclear if we need this long-term, but it's definitelly useful while we 3//! It's unclear if we need this long-term, but it's definitelly useful while we
4//! are splitting the hir. 4//! are splitting the hir.
5 5
6use hir_def::{AdtId, DefWithBodyId, EnumVariantId, ModuleDefId}; 6use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId};
7 7
8use crate::{Adt, DefWithBody, EnumVariant, ModuleDef}; 8use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef};
9 9
10macro_rules! from_id { 10macro_rules! from_id {
11 ($(($id:path, $ty:path)),*) => {$( 11 ($(($id:path, $ty:path)),*) => {$(
@@ -27,6 +27,7 @@ from_id![
27 (hir_def::StaticId, crate::Static), 27 (hir_def::StaticId, crate::Static),
28 (hir_def::ConstId, crate::Const), 28 (hir_def::ConstId, crate::Const),
29 (hir_def::FunctionId, crate::Function), 29 (hir_def::FunctionId, crate::Function),
30 (hir_def::ImplId, crate::ImplBlock),
30 (hir_expand::MacroDefId, crate::MacroDef) 31 (hir_expand::MacroDefId, crate::MacroDef)
31]; 32];
32 33
@@ -71,3 +72,13 @@ impl From<DefWithBody> for DefWithBodyId {
71 } 72 }
72 } 73 }
73} 74}
75
76impl From<AssocItemId> for AssocItem {
77 fn from(def: AssocItemId) -> Self {
78 match def {
79 AssocItemId::FunctionId(it) => AssocItem::Function(it.into()),
80 AssocItemId::TypeAliasId(it) => AssocItem::TypeAlias(it.into()),
81 AssocItemId::ConstId(it) => AssocItem::Const(it.into()),
82 }
83 }
84}
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 7e5523c54..ec56dfa6a 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -82,14 +82,8 @@ impl FromSource for TypeAlias {
82impl FromSource for ImplBlock { 82impl FromSource for ImplBlock {
83 type Ast = ast::ImplBlock; 83 type Ast = ast::ImplBlock;
84 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 84 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
85 let module_src = crate::ModuleSource::from_child_node( 85 let id = from_source(db, src)?;
86 db, 86 Some(ImplBlock { id })
87 src.file_id.original_file(db),
88 &src.ast.syntax(),
89 );
90 let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?;
91 let impls = module.impl_blocks(db);
92 impls.into_iter().find(|b| b.source(db) == src)
93 } 87 }
94} 88}
95 89
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index b1a014074..0c2bb8fee 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -1,88 +1,38 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use rustc_hash::FxHashMap; 3use hir_def::{type_ref::TypeRef, AstItemDef};
4use std::sync::Arc; 4use ra_syntax::ast::{self};
5
6use hir_def::{attr::Attr, type_ref::TypeRef};
7use hir_expand::hygiene::Hygiene;
8use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
9use ra_cfg::CfgOptions;
10use ra_syntax::{
11 ast::{self, AstNode},
12 AstPtr,
13};
14 5
15use crate::{ 6use crate::{
16 code_model::{Module, ModuleSource},
17 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
18 generics::HasGenericParams, 8 generics::HasGenericParams,
19 ids::LocationCtx,
20 ids::MacroCallLoc,
21 resolve::Resolver, 9 resolve::Resolver,
22 ty::Ty, 10 ty::Ty,
23 AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef, 11 AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef,
24 TypeAlias,
25}; 12};
26 13
27#[derive(Debug, Default, PartialEq, Eq)]
28pub struct ImplSourceMap {
29 map: ArenaMap<ImplId, Source<AstPtr<ast::ImplBlock>>>,
30}
31
32impl ImplSourceMap {
33 fn insert(&mut self, impl_id: ImplId, file_id: HirFileId, impl_block: &ast::ImplBlock) {
34 let source = Source { file_id, ast: AstPtr::new(impl_block) };
35 self.map.insert(impl_id, source)
36 }
37
38 pub fn get(&self, db: &impl AstDatabase, impl_id: ImplId) -> Source<ast::ImplBlock> {
39 let src = self.map[impl_id];
40 let root = src.file_syntax(db);
41 src.map(|ptr| ptr.to_node(&root))
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46pub struct ImplBlock {
47 module: Module,
48 impl_id: ImplId,
49}
50
51impl HasSource for ImplBlock { 14impl HasSource for ImplBlock {
52 type Ast = ast::ImplBlock; 15 type Ast = ast::ImplBlock;
53 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> { 16 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> {
54 let source_map = db.impls_in_module_with_source_map(self.module).1; 17 self.id.source(db)
55 source_map.get(db, self.impl_id)
56 } 18 }
57} 19}
58 20
59impl ImplBlock { 21impl ImplBlock {
60 pub(crate) fn containing( 22 pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option<ImplBlock> {
61 module_impl_blocks: Arc<ModuleImplBlocks>, 23 let module = item.module(db);
62 item: AssocItem, 24 let crate_def_map = db.crate_def_map(module.id.krate);
63 ) -> Option<ImplBlock> { 25 crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| {
64 let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; 26 db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item)
65 Some(ImplBlock { module: module_impl_blocks.module, impl_id }) 27 })
66 }
67
68 pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock {
69 ImplBlock { module, impl_id }
70 }
71
72 pub fn id(&self) -> ImplId {
73 self.impl_id
74 }
75
76 pub fn module(&self) -> Module {
77 self.module
78 } 28 }
79 29
80 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 30 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
81 db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() 31 db.impl_data(self.id).target_trait().cloned()
82 } 32 }
83 33
84 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { 34 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
85 db.impls_in_module(self.module).impls[self.impl_id].target_type().clone() 35 db.impl_data(self.id).target_type().clone()
86 } 36 }
87 37
88 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { 38 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
@@ -95,15 +45,23 @@ impl ImplBlock {
95 } 45 }
96 46
97 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { 47 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
98 db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() 48 db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect()
99 } 49 }
100 50
101 pub fn is_negative(&self, db: &impl DefDatabase) -> bool { 51 pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
102 db.impls_in_module(self.module).impls[self.impl_id].negative 52 db.impl_data(self.id).is_negative()
53 }
54
55 pub fn module(&self, db: &impl DefDatabase) -> Module {
56 self.id.module(db).into()
57 }
58
59 pub fn krate(&self, db: &impl DefDatabase) -> Crate {
60 Crate { crate_id: self.module(db).id.krate }
103 } 61 }
104 62
105 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { 63 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
106 let r = self.module().resolver(db); 64 let r = self.module(db).resolver(db);
107 // add generic params, if present 65 // add generic params, if present
108 let p = self.generic_params(db); 66 let p = self.generic_params(db);
109 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; 67 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
@@ -111,175 +69,3 @@ impl ImplBlock {
111 r 69 r
112 } 70 }
113} 71}
114
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub struct ImplData {
117 target_trait: Option<TypeRef>,
118 target_type: TypeRef,
119 items: Vec<AssocItem>,
120 negative: bool,
121}
122
123impl ImplData {
124 pub(crate) fn from_ast(
125 db: &(impl DefDatabase + AstDatabase),
126 file_id: HirFileId,
127 module: Module,
128 node: &ast::ImplBlock,
129 ) -> Self {
130 let target_trait = node.target_trait().map(TypeRef::from_ast);
131 let target_type = TypeRef::from_ast_opt(node.target_type());
132 let ctx = LocationCtx::new(db, module.id, file_id);
133 let negative = node.is_negative();
134 let items = if let Some(item_list) = node.item_list() {
135 item_list
136 .impl_items()
137 .map(|item_node| match item_node {
138 ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(),
139 ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(),
140 ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(),
141 })
142 .collect()
143 } else {
144 Vec::new()
145 };
146 ImplData { target_trait, target_type, items, negative }
147 }
148
149 pub fn target_trait(&self) -> Option<&TypeRef> {
150 self.target_trait.as_ref()
151 }
152
153 pub fn target_type(&self) -> &TypeRef {
154 &self.target_type
155 }
156
157 pub fn items(&self) -> &[AssocItem] {
158 &self.items
159 }
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
163pub struct ImplId(pub RawId);
164impl_arena_id!(ImplId);
165
166/// The collection of impl blocks is a two-step process: first we collect the
167/// blocks per-module; then we build an index of all impl blocks in the crate.
168/// This way, we avoid having to do this process for the whole crate whenever
169/// a file is changed; as long as the impl blocks in the file don't change,
170/// we don't need to do the second step again.
171#[derive(Debug, PartialEq, Eq)]
172pub struct ModuleImplBlocks {
173 pub(crate) module: Module,
174 pub(crate) impls: Arena<ImplId, ImplData>,
175 impls_by_def: FxHashMap<AssocItem, ImplId>,
176}
177
178impl ModuleImplBlocks {
179 pub(crate) fn impls_in_module_with_source_map_query(
180 db: &(impl DefDatabase + AstDatabase),
181 module: Module,
182 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
183 let mut source_map = ImplSourceMap::default();
184 let crate_graph = db.crate_graph();
185 let cfg_options = crate_graph.cfg_options(module.id.krate);
186
187 let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map);
188 (Arc::new(result), Arc::new(source_map))
189 }
190
191 pub(crate) fn impls_in_module_query(
192 db: &impl DefDatabase,
193 module: Module,
194 ) -> Arc<ModuleImplBlocks> {
195 db.impls_in_module_with_source_map(module).0
196 }
197
198 fn collect(
199 db: &(impl DefDatabase + AstDatabase),
200 cfg_options: &CfgOptions,
201 module: Module,
202 source_map: &mut ImplSourceMap,
203 ) -> Self {
204 let mut m = ModuleImplBlocks {
205 module,
206 impls: Arena::default(),
207 impls_by_def: FxHashMap::default(),
208 };
209
210 let src = m.module.definition_source(db);
211 match &src.ast {
212 ModuleSource::SourceFile(node) => {
213 m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id)
214 }
215 ModuleSource::Module(node) => {
216 let item_list = node.item_list().expect("inline module should have item list");
217 m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id)
218 }
219 };
220 m
221 }
222
223 fn collect_from_item_owner(
224 &mut self,
225 db: &(impl DefDatabase + AstDatabase),
226 cfg_options: &CfgOptions,
227 source_map: &mut ImplSourceMap,
228 owner: &dyn ast::ModuleItemOwner,
229 file_id: HirFileId,
230 ) {
231 let hygiene = Hygiene::new(db, file_id);
232 for item in owner.items_with_macros() {
233 match item {
234 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
235 let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene);
236 if attrs.map_or(false, |attrs| {
237 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
238 }) {
239 continue;
240 }
241
242 let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast);
243 let id = self.impls.alloc(impl_block);
244 for &impl_item in &self.impls[id].items {
245 self.impls_by_def.insert(impl_item, id);
246 }
247
248 source_map.insert(id, file_id, &impl_block_ast);
249 }
250 ast::ItemOrMacro::Item(_) => (),
251 ast::ItemOrMacro::Macro(macro_call) => {
252 let attrs = Attr::from_attrs_owner(&macro_call, &hygiene);
253 if attrs.map_or(false, |attrs| {
254 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
255 }) {
256 continue;
257 }
258
259 //FIXME: we should really cut down on the boilerplate required to process a macro
260 let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(&macro_call));
261 if let Some(path) =
262 macro_call.path().and_then(|path| Path::from_src(path, &hygiene))
263 {
264 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
265 {
266 let call_id = db.intern_macro(MacroCallLoc { def: def.id, ast_id });
267 let file_id = call_id.as_file(MacroFileKind::Items);
268 if let Some(item_list) =
269 db.parse_or_expand(file_id).and_then(ast::MacroItems::cast)
270 {
271 self.collect_from_item_owner(
272 db,
273 cfg_options,
274 source_map,
275 &item_list,
276 file_id,
277 )
278 }
279 }
280 }
281 }
282 }
283 }
284 }
285}
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index e1780ed38..fa2ef8a17 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -25,7 +25,7 @@ impl LangItemTarget {
25 Some(match self { 25 Some(match self {
26 LangItemTarget::Enum(e) => e.module(db).krate(), 26 LangItemTarget::Enum(e) => e.module(db).krate(),
27 LangItemTarget::Function(f) => f.module(db).krate(), 27 LangItemTarget::Function(f) => f.module(db).krate(),
28 LangItemTarget::ImplBlock(i) => i.module().krate(), 28 LangItemTarget::ImplBlock(i) => i.krate(db),
29 LangItemTarget::Static(s) => s.module(db).krate(), 29 LangItemTarget::Static(s) => s.module(db).krate(),
30 LangItemTarget::Struct(s) => s.module(db).krate(), 30 LangItemTarget::Struct(s) => s.module(db).krate(),
31 LangItemTarget::Trait(t) => t.module(db).krate(), 31 LangItemTarget::Trait(t) => t.module(db).krate(),
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 5ba847d35..da33c9591 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -54,12 +54,11 @@ mod test_db;
54#[cfg(test)] 54#[cfg(test)]
55mod marks; 55mod marks;
56 56
57use hir_expand::AstId; 57use crate::resolve::Resolver;
58
59use crate::{ids::MacroFileKind, resolve::Resolver};
60 58
61pub use crate::{ 59pub use crate::{
62 adt::VariantDef, 60 adt::VariantDef,
61 code_model::ImplBlock,
63 code_model::{ 62 code_model::{
64 attrs::{AttrDef, Attrs}, 63 attrs::{AttrDef, Attrs},
65 docs::{DocDef, Docs, Documentation}, 64 docs::{DocDef, Docs, Documentation},
@@ -72,7 +71,6 @@ pub use crate::{
72 from_source::FromSource, 71 from_source::FromSource,
73 generics::GenericDef, 72 generics::GenericDef,
74 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, 73 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
75 impl_block::ImplBlock,
76 resolve::ScopeDef, 74 resolve::ScopeDef,
77 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 75 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
78 ty::{ 76 ty::{
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 2fb913108..79b92180a 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -15,9 +15,8 @@ use crate::{
15 db::{DefDatabase, HirDatabase}, 15 db::{DefDatabase, HirDatabase},
16 expr::{ExprScopes, PatId, ScopeId}, 16 expr::{ExprScopes, PatId, ScopeId},
17 generics::GenericParams, 17 generics::GenericParams,
18 impl_block::ImplBlock, 18 Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef,
19 Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, 19 PerNs, Static, Struct, Trait, TypeAlias,
20 Static, Struct, Trait, TypeAlias,
21}; 20};
22 21
23#[derive(Debug, Clone, Default)] 22#[derive(Debug, Clone, Default)]
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index eb5ca6769..9aad2d3fe 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -5,16 +5,14 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::CrateModuleId;
9use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
10 9
11use crate::{ 10use crate::{
12 db::HirDatabase, 11 db::HirDatabase,
13 impl_block::{ImplBlock, ImplId},
14 resolve::Resolver, 12 resolve::Resolver,
15 ty::primitive::{FloatBitness, Uncertain}, 13 ty::primitive::{FloatBitness, Uncertain},
16 ty::{Ty, TypeCtor}, 14 ty::{Ty, TypeCtor},
17 AssocItem, Crate, Function, Module, Mutability, Name, Trait, 15 AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait,
18}; 16};
19 17
20use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 18use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
@@ -39,65 +37,46 @@ impl TyFingerprint {
39 37
40#[derive(Debug, PartialEq, Eq)] 38#[derive(Debug, PartialEq, Eq)]
41pub struct CrateImplBlocks { 39pub struct CrateImplBlocks {
42 /// To make sense of the CrateModuleIds, we need the source root. 40 impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>,
43 krate: Crate, 41 impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>,
44 impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
45 impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
46} 42}
47 43
48impl CrateImplBlocks { 44impl CrateImplBlocks {
49 pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + 'a { 45 pub(crate) fn impls_in_crate_query(
46 db: &impl HirDatabase,
47 krate: Crate,
48 ) -> Arc<CrateImplBlocks> {
49 let mut crate_impl_blocks =
50 CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() };
51 if let Some(module) = krate.root_module(db) {
52 crate_impl_blocks.collect_recursive(db, module);
53 }
54 Arc::new(crate_impl_blocks)
55 }
56 pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + '_ {
50 let fingerprint = TyFingerprint::for_impl(ty); 57 let fingerprint = TyFingerprint::for_impl(ty);
51 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map( 58 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
52 move |(module_id, impl_id)| {
53 let module = Module::new(self.krate, *module_id);
54 ImplBlock::from_id(module, *impl_id)
55 },
56 )
57 } 59 }
58 60
59 pub fn lookup_impl_blocks_for_trait<'a>( 61 pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ {
60 &'a self, 62 self.impls_by_trait.get(&tr).into_iter().flatten().copied()
61 tr: Trait,
62 ) -> impl Iterator<Item = ImplBlock> + 'a {
63 self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
64 move |(module_id, impl_id)| {
65 let module = Module::new(self.krate, *module_id);
66 ImplBlock::from_id(module, *impl_id)
67 },
68 )
69 } 63 }
70 64
71 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { 65 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a {
72 self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map( 66 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
73 move |(module_id, impl_id)| {
74 let module = Module::new(self.krate, *module_id);
75 ImplBlock::from_id(module, *impl_id)
76 },
77 )
78 } 67 }
79 68
80 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { 69 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
81 let module_impl_blocks = db.impls_in_module(module); 70 for impl_block in module.impl_blocks(db) {
82
83 for (impl_id, _) in module_impl_blocks.impls.iter() {
84 let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id);
85
86 let target_ty = impl_block.target_ty(db); 71 let target_ty = impl_block.target_ty(db);
87 72
88 if impl_block.target_trait(db).is_some() { 73 if impl_block.target_trait(db).is_some() {
89 if let Some(tr) = impl_block.target_trait_ref(db) { 74 if let Some(tr) = impl_block.target_trait_ref(db) {
90 self.impls_by_trait 75 self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block);
91 .entry(tr.trait_)
92 .or_insert_with(Vec::new)
93 .push((module.id.module_id, impl_id));
94 } 76 }
95 } else { 77 } else {
96 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 78 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
97 self.impls 79 self.impls.entry(target_ty_fp).or_default().push(impl_block);
98 .entry(target_ty_fp)
99 .or_insert_with(Vec::new)
100 .push((module.id.module_id, impl_id));
101 } 80 }
102 } 81 }
103 } 82 }
@@ -106,21 +85,6 @@ impl CrateImplBlocks {
106 self.collect_recursive(db, child); 85 self.collect_recursive(db, child);
107 } 86 }
108 } 87 }
109
110 pub(crate) fn impls_in_crate_query(
111 db: &impl HirDatabase,
112 krate: Crate,
113 ) -> Arc<CrateImplBlocks> {
114 let mut crate_impl_blocks = CrateImplBlocks {
115 krate,
116 impls: FxHashMap::default(),
117 impls_by_trait: FxHashMap::default(),
118 };
119 if let Some(module) = krate.root_module(db) {
120 crate_impl_blocks.collect_recursive(db, module);
121 }
122 Arc::new(crate_impl_blocks)
123 }
124} 88}
125 89
126fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { 90fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> {
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 75351c17d..68304b950 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -191,11 +191,11 @@ impl ToChalk for Impl {
191 type Chalk = chalk_ir::ImplId; 191 type Chalk = chalk_ir::ImplId;
192 192
193 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { 193 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId {
194 db.intern_impl(self).into() 194 db.intern_chalk_impl(self).into()
195 } 195 }
196 196
197 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { 197 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl {
198 db.lookup_intern_impl(impl_id.into()) 198 db.lookup_intern_chalk_impl(impl_id.into())
199 } 199 }
200} 200}
201 201
@@ -630,7 +630,7 @@ fn impl_block_datum(
630 .target_trait_ref(db) 630 .target_trait_ref(db)
631 .expect("FIXME handle unresolved impl block trait ref") 631 .expect("FIXME handle unresolved impl block trait ref")
632 .subst(&bound_vars); 632 .subst(&bound_vars);
633 let impl_type = if impl_block.module().krate() == krate { 633 let impl_type = if impl_block.krate(db) == krate {
634 chalk_rust_ir::ImplType::Local 634 chalk_rust_ir::ImplType::Local
635 } else { 635 } else {
636 chalk_rust_ir::ImplType::External 636 chalk_rust_ir::ImplType::External
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..0a59c4ad7 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;
@@ -321,6 +322,18 @@ impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
321 } 322 }
322} 323}
323 324
325#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
326pub struct ImplId(salsa::InternId);
327impl_intern_key!(ImplId);
328impl AstItemDef<ast::ImplBlock> for ImplId {
329 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ImplBlock>) -> Self {
330 db.intern_impl(loc)
331 }
332 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ImplBlock> {
333 db.lookup_intern_impl(self)
334 }
335}
336
324macro_rules! impl_froms { 337macro_rules! impl_froms {
325 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 338 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
326 $( 339 $(
@@ -384,3 +397,15 @@ pub enum DefWithBodyId {
384} 397}
385 398
386impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); 399impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId);
400
401#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
402pub enum AssocItemId {
403 FunctionId(FunctionId),
404 ConstId(ConstId),
405 TypeAliasId(TypeAliasId),
406}
407// FIXME: not every function, ... is actually an assoc item. maybe we should make
408// sure that you can only turn actual assoc items into AssocItemIds. This would
409// require not implementing From, and instead having some checked way of
410// casting them, and somehow making the constructors private, which would be annoying.
411impl_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..49e33ccc4 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,6 +122,7 @@ 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, Clone)]
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>,
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 010b45141..5c9dec13e 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -271,7 +271,6 @@ impl RootDatabase {
271 self.query(hir::db::AstIdMapQuery).sweep(sweep); 271 self.query(hir::db::AstIdMapQuery).sweep(sweep);
272 272
273 self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); 273 self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep);
274 self.query(hir::db::ImplsInModuleWithSourceMapQuery).sweep(sweep);
275 self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); 274 self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);
276 275
277 self.query(hir::db::ExprScopesQuery).sweep(sweep); 276 self.query(hir::db::ExprScopesQuery).sweep(sweep);
@@ -314,8 +313,6 @@ impl RootDatabase {
314 hir::db::RawItemsWithSourceMapQuery 313 hir::db::RawItemsWithSourceMapQuery
315 hir::db::RawItemsQuery 314 hir::db::RawItemsQuery
316 hir::db::CrateDefMapQuery 315 hir::db::CrateDefMapQuery
317 hir::db::ImplsInModuleWithSourceMapQuery
318 hir::db::ImplsInModuleQuery
319 hir::db::GenericParamsQuery 316 hir::db::GenericParamsQuery
320 hir::db::FnDataQuery 317 hir::db::FnDataQuery
321 hir::db::TypeAliasDataQuery 318 hir::db::TypeAliasDataQuery
@@ -340,6 +337,7 @@ impl RootDatabase {
340 hir::db::TraitDatumQuery 337 hir::db::TraitDatumQuery
341 hir::db::StructDatumQuery 338 hir::db::StructDatumQuery
342 hir::db::ImplDatumQuery 339 hir::db::ImplDatumQuery
340 hir::db::ImplDataQuery
343 hir::db::TraitSolveQuery 341 hir::db::TraitSolveQuery
344 ]; 342 ];
345 acc.sort_by_key(|it| std::cmp::Reverse(it.1)); 343 acc.sort_by_key(|it| std::cmp::Reverse(it.1));
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index 217f9951e..00690e449 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -114,8 +114,6 @@ pub(crate) fn classify_name_ref(
114 file_id: FileId, 114 file_id: FileId,
115 name_ref: &ast::NameRef, 115 name_ref: &ast::NameRef,
116) -> Option<NameDefinition> { 116) -> Option<NameDefinition> {
117 use PathResolution::*;
118
119 let _p = profile("classify_name_ref"); 117 let _p = profile("classify_name_ref");
120 118
121 let parent = name_ref.syntax().parent()?; 119 let parent = name_ref.syntax().parent()?;
@@ -163,26 +161,26 @@ pub(crate) fn classify_name_ref(
163 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 161 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
164 let resolved = analyzer.resolve_path(db, &path)?; 162 let resolved = analyzer.resolve_path(db, &path)?;
165 match resolved { 163 match resolved {
166 Def(def) => Some(from_module_def(db, def, Some(container))), 164 PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))),
167 AssocItem(item) => Some(from_assoc_item(db, item)), 165 PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)),
168 Local(local) => { 166 PathResolution::Local(local) => {
169 let container = local.module(db); 167 let container = local.module(db);
170 let kind = NameKind::Local(local); 168 let kind = NameKind::Local(local);
171 Some(NameDefinition { kind, container, visibility: None }) 169 Some(NameDefinition { kind, container, visibility: None })
172 } 170 }
173 GenericParam(par) => { 171 PathResolution::GenericParam(par) => {
174 // FIXME: get generic param def 172 // FIXME: get generic param def
175 let kind = NameKind::GenericParam(par); 173 let kind = NameKind::GenericParam(par);
176 Some(NameDefinition { kind, container, visibility }) 174 Some(NameDefinition { kind, container, visibility })
177 } 175 }
178 Macro(def) => { 176 PathResolution::Macro(def) => {
179 let kind = NameKind::Macro(def); 177 let kind = NameKind::Macro(def);
180 Some(NameDefinition { kind, container, visibility }) 178 Some(NameDefinition { kind, container, visibility })
181 } 179 }
182 SelfType(impl_block) => { 180 PathResolution::SelfType(impl_block) => {
183 let ty = impl_block.target_ty(db); 181 let ty = impl_block.target_ty(db);
184 let kind = NameKind::SelfType(ty); 182 let kind = NameKind::SelfType(ty);
185 let container = impl_block.module(); 183 let container = impl_block.module(db);
186 Some(NameDefinition { kind, container, visibility }) 184 Some(NameDefinition { kind, container, visibility })
187 } 185 }
188 } 186 }