diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-12 21:18:14 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-12 21:18:14 +0000 |
commit | eb931c0d9e0877e573622253ae5b05563841037b (patch) | |
tree | 653ef81450a4d39c5b46f98c97c23fa8586dd7f8 /crates/ra_hir/src/impl_block.rs | |
parent | e56072bfa3e5af69a4c293a38de6e1350ada3573 (diff) | |
parent | 1ed7fbfc1badd2c2a42b4dc2feb1b4bf7835d3ef (diff) |
Merge #505
505: Inherent methods r=matklad a=flodiebold
This adds resolution, type checking and completion for inherent methods.
The main open question here is the caching, I think. I'm not sure whether we should be caching method resolutions in a more fine grained way (currently we just build a hash map of types -> impl blocks, and iterate through all potential impl blocks when looking for a method).
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/impl_block.rs')
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 4acda9af3..d0b086308 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -33,20 +33,27 @@ impl ImplBlock { | |||
33 | }) | 33 | }) |
34 | } | 34 | } |
35 | 35 | ||
36 | pub(crate) fn from_id(module_impl_blocks: Arc<ModuleImplBlocks>, impl_id: ImplId) -> ImplBlock { | ||
37 | ImplBlock { | ||
38 | module_impl_blocks, | ||
39 | impl_id, | ||
40 | } | ||
41 | } | ||
42 | |||
36 | fn impl_data(&self) -> &ImplData { | 43 | fn impl_data(&self) -> &ImplData { |
37 | &self.module_impl_blocks.impls[self.impl_id] | 44 | &self.module_impl_blocks.impls[self.impl_id] |
38 | } | 45 | } |
39 | 46 | ||
40 | pub fn target_trait(&self) -> Option<&TypeRef> { | 47 | pub fn target_trait(&self) -> Option<&TypeRef> { |
41 | self.impl_data().target_trait.as_ref() | 48 | self.impl_data().target_trait() |
42 | } | 49 | } |
43 | 50 | ||
44 | pub fn target_type(&self) -> &TypeRef { | 51 | pub fn target_type(&self) -> &TypeRef { |
45 | &self.impl_data().target_type | 52 | self.impl_data().target_type() |
46 | } | 53 | } |
47 | 54 | ||
48 | pub fn items(&self) -> &[ImplItem] { | 55 | pub fn items(&self) -> &[ImplItem] { |
49 | &self.impl_data().items | 56 | self.impl_data().items() |
50 | } | 57 | } |
51 | } | 58 | } |
52 | 59 | ||
@@ -64,7 +71,7 @@ impl ImplData { | |||
64 | module: &Module, | 71 | module: &Module, |
65 | node: &ast::ImplBlock, | 72 | node: &ast::ImplBlock, |
66 | ) -> Self { | 73 | ) -> Self { |
67 | let target_trait = node.target_type().map(TypeRef::from_ast); | 74 | let target_trait = node.target_trait().map(TypeRef::from_ast); |
68 | let target_type = TypeRef::from_ast_opt(node.target_type()); | 75 | let target_type = TypeRef::from_ast_opt(node.target_type()); |
69 | let module_loc = module.def_id.loc(db); | 76 | let module_loc = module.def_id.loc(db); |
70 | let items = if let Some(item_list) = node.item_list() { | 77 | let items = if let Some(item_list) = node.item_list() { |
@@ -103,6 +110,18 @@ impl ImplData { | |||
103 | items, | 110 | items, |
104 | } | 111 | } |
105 | } | 112 | } |
113 | |||
114 | pub fn target_trait(&self) -> Option<&TypeRef> { | ||
115 | self.target_trait.as_ref() | ||
116 | } | ||
117 | |||
118 | pub fn target_type(&self) -> &TypeRef { | ||
119 | &self.target_type | ||
120 | } | ||
121 | |||
122 | pub fn items(&self) -> &[ImplItem] { | ||
123 | &self.items | ||
124 | } | ||
106 | } | 125 | } |
107 | 126 | ||
108 | #[derive(Debug, Clone, PartialEq, Eq)] | 127 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -133,11 +152,9 @@ impl_arena_id!(ImplId); | |||
133 | /// This way, we avoid having to do this process for the whole crate whenever | 152 | /// This way, we avoid having to do this process for the whole crate whenever |
134 | /// a file is changed; as long as the impl blocks in the file don't change, | 153 | /// a file is changed; as long as the impl blocks in the file don't change, |
135 | /// we don't need to do the second step again. | 154 | /// we don't need to do the second step again. |
136 | /// | ||
137 | /// (The second step does not yet exist.) | ||
138 | #[derive(Debug, PartialEq, Eq)] | 155 | #[derive(Debug, PartialEq, Eq)] |
139 | pub struct ModuleImplBlocks { | 156 | pub struct ModuleImplBlocks { |
140 | impls: Arena<ImplId, ImplData>, | 157 | pub(crate) impls: Arena<ImplId, ImplData>, |
141 | impls_by_def: FxHashMap<DefId, ImplId>, | 158 | impls_by_def: FxHashMap<DefId, ImplId>, |
142 | } | 159 | } |
143 | 160 | ||
@@ -153,7 +170,10 @@ impl ModuleImplBlocks { | |||
153 | let (file_id, module_source) = module.definition_source(db)?; | 170 | let (file_id, module_source) = module.definition_source(db)?; |
154 | let node = match &module_source { | 171 | let node = match &module_source { |
155 | ModuleSource::SourceFile(node) => node.syntax(), | 172 | ModuleSource::SourceFile(node) => node.syntax(), |
156 | ModuleSource::Module(node) => node.syntax(), | 173 | ModuleSource::Module(node) => node |
174 | .item_list() | ||
175 | .expect("inline module should have item list") | ||
176 | .syntax(), | ||
157 | }; | 177 | }; |
158 | 178 | ||
159 | let source_file_items = db.file_items(file_id.into()); | 179 | let source_file_items = db.file_items(file_id.into()); |