diff options
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 260 | ||||
-rw-r--r-- | crates/ra_hir/src/lang_item.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 80 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/db.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_def/src/imp.rs | 71 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/raw.rs | 29 | ||||
-rw-r--r-- | crates/ra_ide_api/src/change.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 16 |
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 | }; |
16 | use hir_expand::{ | 16 | use 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)] | ||
1134 | pub 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 | ||
25 | pub use hir_def::db::{ | 24 | pub 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 | }; |
30 | pub use hir_expand::db::{ | 29 | pub 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 | ||
6 | use hir_def::{AdtId, DefWithBodyId, EnumVariantId, ModuleDefId}; | 6 | use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; |
7 | 7 | ||
8 | use crate::{Adt, DefWithBody, EnumVariant, ModuleDef}; | 8 | use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; |
9 | 9 | ||
10 | macro_rules! from_id { | 10 | macro_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 | |||
76 | impl 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 { | |||
82 | impl FromSource for ImplBlock { | 82 | impl 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 | ||
3 | use rustc_hash::FxHashMap; | 3 | use hir_def::{type_ref::TypeRef, AstItemDef}; |
4 | use std::sync::Arc; | 4 | use ra_syntax::ast::{self}; |
5 | |||
6 | use hir_def::{attr::Attr, type_ref::TypeRef}; | ||
7 | use hir_expand::hygiene::Hygiene; | ||
8 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | ||
9 | use ra_cfg::CfgOptions; | ||
10 | use ra_syntax::{ | ||
11 | ast::{self, AstNode}, | ||
12 | AstPtr, | ||
13 | }; | ||
14 | 5 | ||
15 | use crate::{ | 6 | use 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)] | ||
28 | pub struct ImplSourceMap { | ||
29 | map: ArenaMap<ImplId, Source<AstPtr<ast::ImplBlock>>>, | ||
30 | } | ||
31 | |||
32 | impl 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)] | ||
46 | pub struct ImplBlock { | ||
47 | module: Module, | ||
48 | impl_id: ImplId, | ||
49 | } | ||
50 | |||
51 | impl HasSource for ImplBlock { | 14 | impl 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 | ||
59 | impl ImplBlock { | 21 | impl 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)] | ||
116 | pub struct ImplData { | ||
117 | target_trait: Option<TypeRef>, | ||
118 | target_type: TypeRef, | ||
119 | items: Vec<AssocItem>, | ||
120 | negative: bool, | ||
121 | } | ||
122 | |||
123 | impl 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)] | ||
163 | pub struct ImplId(pub RawId); | ||
164 | impl_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)] | ||
172 | pub struct ModuleImplBlocks { | ||
173 | pub(crate) module: Module, | ||
174 | pub(crate) impls: Arena<ImplId, ImplData>, | ||
175 | impls_by_def: FxHashMap<AssocItem, ImplId>, | ||
176 | } | ||
177 | |||
178 | impl 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(¯o_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(¯o_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)] |
55 | mod marks; | 55 | mod marks; |
56 | 56 | ||
57 | use hir_expand::AstId; | 57 | use crate::resolve::Resolver; |
58 | |||
59 | use crate::{ids::MacroFileKind, resolve::Resolver}; | ||
60 | 58 | ||
61 | pub use crate::{ | 59 | pub 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 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::CrateModuleId; | ||
9 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
10 | 9 | ||
11 | use crate::{ | 10 | use 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 | ||
20 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 18 | use 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)] |
41 | pub struct CrateImplBlocks { | 39 | pub 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 | ||
48 | impl CrateImplBlocks { | 44 | impl 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 | ||
126 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { | 90 | fn 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; | |||
8 | use crate::{ | 8 | use 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)] |
19 | pub trait InternDatabase: SourceDatabase { | 20 | pub 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 | |||
6 | use std::sync::Arc; | ||
7 | |||
8 | use ra_syntax::ast; | ||
9 | |||
10 | use crate::{ | ||
11 | db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, | ||
12 | LocationCtx, TypeAliasId, | ||
13 | }; | ||
14 | |||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
16 | pub struct ImplData { | ||
17 | target_trait: Option<TypeRef>, | ||
18 | target_type: TypeRef, | ||
19 | items: Vec<AssocItemId>, | ||
20 | negative: bool, | ||
21 | } | ||
22 | |||
23 | impl 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; | |||
13 | pub mod type_ref; | 13 | pub mod type_ref; |
14 | pub mod builtin_type; | 14 | pub mod builtin_type; |
15 | pub mod adt; | 15 | pub mod adt; |
16 | pub mod imp; | ||
16 | pub mod diagnostics; | 17 | pub mod diagnostics; |
17 | pub mod expr; | 18 | pub mod expr; |
18 | pub mod body; | 19 | pub 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)] | ||
326 | pub struct ImplId(salsa::InternId); | ||
327 | impl_intern_key!(ImplId); | ||
328 | impl 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 | |||
324 | macro_rules! impl_froms { | 337 | macro_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 | ||
386 | impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); | 399 | impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); |
400 | |||
401 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
402 | pub 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. | ||
411 | impl_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 | ||
125 | impl 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. |
125 | type Attrs = Option<Arc<[Attr]>>; | 133 | type 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)] | ||
216 | pub(super) struct Impl(RawId); | ||
217 | impl_arena_id!(Impl); | ||
218 | |||
219 | #[derive(Debug, PartialEq, Eq)] | ||
220 | pub(super) struct ImplData { | ||
221 | pub(super) ast_id: FileAstId<ast::ImplBlock>, | ||
222 | } | ||
223 | |||
206 | struct RawItemsCollector { | 224 | struct 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 | } |