diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/child_by_source.rs | 139 | ||||
-rw-r--r-- | crates/ra_hir_def/src/child_from_source.rs | 276 | ||||
-rw-r--r-- | crates/ra_hir_def/src/dyn_map.rs | 108 | ||||
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 171 | ||||
-rw-r--r-- | crates/ra_hir_def/src/keys.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/per_ns.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 38 |
10 files changed, 446 insertions, 376 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7b385f3fd..b3bc336cf 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -6,9 +6,7 @@ pub mod scope; | |||
6 | use std::{ops::Index, sync::Arc}; | 6 | use std::{ops::Index, sync::Arc}; |
7 | 7 | ||
8 | use either::Either; | 8 | use either::Either; |
9 | use hir_expand::{ | 9 | use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; |
10 | hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, MacroFileKind, | ||
11 | }; | ||
12 | use ra_arena::{map::ArenaMap, Arena}; | 10 | use ra_arena::{map::ArenaMap, Arena}; |
13 | use ra_syntax::{ast, AstNode, AstPtr}; | 11 | use ra_syntax::{ast, AstNode, AstPtr}; |
14 | use rustc_hash::FxHashMap; | 12 | use rustc_hash::FxHashMap; |
@@ -49,7 +47,7 @@ impl Expander { | |||
49 | if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { | 47 | if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { |
50 | if let Some(def) = self.resolve_path_as_macro(db, &path) { | 48 | if let Some(def) = self.resolve_path_as_macro(db, &path) { |
51 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); | 49 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); |
52 | let file_id = call_id.as_file(MacroFileKind::Expr); | 50 | let file_id = call_id.as_file(); |
53 | if let Some(node) = db.parse_or_expand(file_id) { | 51 | if let Some(node) = db.parse_or_expand(file_id) { |
54 | if let Some(expr) = ast::Expr::cast(node) { | 52 | if let Some(expr) = ast::Expr::cast(node) { |
55 | log::debug!("macro expansion {:#?}", expr.syntax()); | 53 | log::debug!("macro expansion {:#?}", expr.syntax()); |
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs new file mode 100644 index 000000000..a3574a9db --- /dev/null +++ b/crates/ra_hir_def/src/child_by_source.rs | |||
@@ -0,0 +1,139 @@ | |||
1 | //! When *constructing* `hir`, we start at some parent syntax node and recursively | ||
2 | //! lower the children. | ||
3 | //! | ||
4 | //! This modules allows one to go in the opposite direction: start with a syntax | ||
5 | //! node for a *child*, and get its hir. | ||
6 | |||
7 | use either::Either; | ||
8 | |||
9 | use crate::{ | ||
10 | db::DefDatabase, | ||
11 | dyn_map::DynMap, | ||
12 | keys, | ||
13 | src::{HasChildSource, HasSource}, | ||
14 | AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, StructFieldId, | ||
15 | TraitId, VariantId, | ||
16 | }; | ||
17 | |||
18 | pub trait ChildBySource { | ||
19 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap; | ||
20 | } | ||
21 | |||
22 | impl ChildBySource for TraitId { | ||
23 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { | ||
24 | let mut res = DynMap::default(); | ||
25 | |||
26 | let data = db.trait_data(*self); | ||
27 | for (_name, item) in data.items.iter() { | ||
28 | match *item { | ||
29 | AssocItemId::FunctionId(func) => { | ||
30 | let src = func.lookup(db).source(db); | ||
31 | res[keys::FUNCTION].insert(src, func) | ||
32 | } | ||
33 | AssocItemId::ConstId(konst) => { | ||
34 | let src = konst.lookup(db).source(db); | ||
35 | res[keys::CONST].insert(src, konst) | ||
36 | } | ||
37 | AssocItemId::TypeAliasId(ty) => { | ||
38 | let src = ty.lookup(db).source(db); | ||
39 | res[keys::TYPE_ALIAS].insert(src, ty) | ||
40 | } | ||
41 | } | ||
42 | } | ||
43 | |||
44 | res | ||
45 | } | ||
46 | } | ||
47 | |||
48 | impl ChildBySource for ImplId { | ||
49 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { | ||
50 | let mut res = DynMap::default(); | ||
51 | |||
52 | let data = db.impl_data(*self); | ||
53 | for &item in data.items.iter() { | ||
54 | match item { | ||
55 | AssocItemId::FunctionId(func) => { | ||
56 | let src = func.lookup(db).source(db); | ||
57 | res[keys::FUNCTION].insert(src, func) | ||
58 | } | ||
59 | AssocItemId::ConstId(konst) => { | ||
60 | let src = konst.lookup(db).source(db); | ||
61 | res[keys::CONST].insert(src, konst) | ||
62 | } | ||
63 | AssocItemId::TypeAliasId(ty) => { | ||
64 | let src = ty.lookup(db).source(db); | ||
65 | res[keys::TYPE_ALIAS].insert(src, ty) | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | res | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl ChildBySource for ModuleId { | ||
75 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { | ||
76 | let mut res = DynMap::default(); | ||
77 | |||
78 | let crate_def_map = db.crate_def_map(self.krate); | ||
79 | for item in crate_def_map[self.local_id].scope.declarations() { | ||
80 | match item { | ||
81 | ModuleDefId::FunctionId(func) => { | ||
82 | let src = func.lookup(db).source(db); | ||
83 | res[keys::FUNCTION].insert(src, func) | ||
84 | } | ||
85 | ModuleDefId::ConstId(konst) => { | ||
86 | let src = konst.lookup(db).source(db); | ||
87 | res[keys::CONST].insert(src, konst) | ||
88 | } | ||
89 | ModuleDefId::StaticId(statik) => { | ||
90 | let src = statik.lookup(db).source(db); | ||
91 | res[keys::STATIC].insert(src, statik) | ||
92 | } | ||
93 | ModuleDefId::TypeAliasId(ty) => { | ||
94 | let src = ty.lookup(db).source(db); | ||
95 | res[keys::TYPE_ALIAS].insert(src, ty) | ||
96 | } | ||
97 | _ => (), | ||
98 | } | ||
99 | } | ||
100 | |||
101 | res | ||
102 | } | ||
103 | } | ||
104 | |||
105 | impl ChildBySource for VariantId { | ||
106 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { | ||
107 | let mut res = DynMap::default(); | ||
108 | |||
109 | let arena_map = self.child_source(db); | ||
110 | let arena_map = arena_map.as_ref(); | ||
111 | for (local_id, source) in arena_map.value.iter() { | ||
112 | let id = StructFieldId { parent: *self, local_id }; | ||
113 | match source { | ||
114 | Either::Left(source) => { | ||
115 | res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id) | ||
116 | } | ||
117 | Either::Right(source) => { | ||
118 | res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id) | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | res | ||
123 | } | ||
124 | } | ||
125 | |||
126 | impl ChildBySource for EnumId { | ||
127 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { | ||
128 | let mut res = DynMap::default(); | ||
129 | |||
130 | let arena_map = self.child_source(db); | ||
131 | let arena_map = arena_map.as_ref(); | ||
132 | for (local_id, source) in arena_map.value.iter() { | ||
133 | let id = EnumVariantId { parent: *self, local_id }; | ||
134 | res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id) | ||
135 | } | ||
136 | |||
137 | res | ||
138 | } | ||
139 | } | ||
diff --git a/crates/ra_hir_def/src/child_from_source.rs b/crates/ra_hir_def/src/child_from_source.rs deleted file mode 100644 index 37d4b7870..000000000 --- a/crates/ra_hir_def/src/child_from_source.rs +++ /dev/null | |||
@@ -1,276 +0,0 @@ | |||
1 | //! When *constructing* `hir`, we start at some parent syntax node and recursively | ||
2 | //! lower the children. | ||
3 | //! | ||
4 | //! This modules allows one to go in the opposite direction: start with a syntax | ||
5 | //! node for a *child*, and get its hir. | ||
6 | |||
7 | use either::Either; | ||
8 | use hir_expand::InFile; | ||
9 | use ra_syntax::{ast, AstNode, AstPtr}; | ||
10 | |||
11 | use crate::{ | ||
12 | db::DefDatabase, | ||
13 | src::{HasChildSource, HasSource}, | ||
14 | AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, ImplId, Lookup, ModuleDefId, ModuleId, | ||
15 | StaticId, StructFieldId, TraitId, TypeAliasId, VariantId, | ||
16 | }; | ||
17 | |||
18 | pub trait ChildFromSource<CHILD, SOURCE> { | ||
19 | fn child_from_source( | ||
20 | &self, | ||
21 | db: &impl DefDatabase, | ||
22 | child_source: InFile<SOURCE>, | ||
23 | ) -> Option<CHILD>; | ||
24 | } | ||
25 | |||
26 | impl ChildFromSource<FunctionId, ast::FnDef> for TraitId { | ||
27 | fn child_from_source( | ||
28 | &self, | ||
29 | db: &impl DefDatabase, | ||
30 | child_source: InFile<ast::FnDef>, | ||
31 | ) -> Option<FunctionId> { | ||
32 | let data = db.trait_data(*self); | ||
33 | data.items | ||
34 | .iter() | ||
35 | .filter_map(|(_, item)| match item { | ||
36 | AssocItemId::FunctionId(it) => Some(*it), | ||
37 | _ => None, | ||
38 | }) | ||
39 | .find(|func| { | ||
40 | let source = func.lookup(db).source(db); | ||
41 | same_source(&source, &child_source) | ||
42 | }) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | impl ChildFromSource<FunctionId, ast::FnDef> for ImplId { | ||
47 | fn child_from_source( | ||
48 | &self, | ||
49 | db: &impl DefDatabase, | ||
50 | child_source: InFile<ast::FnDef>, | ||
51 | ) -> Option<FunctionId> { | ||
52 | let data = db.impl_data(*self); | ||
53 | data.items | ||
54 | .iter() | ||
55 | .filter_map(|item| match item { | ||
56 | AssocItemId::FunctionId(it) => Some(*it), | ||
57 | _ => None, | ||
58 | }) | ||
59 | .find(|func| { | ||
60 | let source = func.lookup(db).source(db); | ||
61 | same_source(&source, &child_source) | ||
62 | }) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | impl ChildFromSource<FunctionId, ast::FnDef> for ModuleId { | ||
67 | fn child_from_source( | ||
68 | &self, | ||
69 | db: &impl DefDatabase, | ||
70 | child_source: InFile<ast::FnDef>, | ||
71 | ) -> Option<FunctionId> { | ||
72 | let crate_def_map = db.crate_def_map(self.krate); | ||
73 | let res = crate_def_map[self.local_id] | ||
74 | .scope | ||
75 | .declarations() | ||
76 | .filter_map(|item| match item { | ||
77 | ModuleDefId::FunctionId(it) => Some(it), | ||
78 | _ => None, | ||
79 | }) | ||
80 | .find(|func| { | ||
81 | let source = func.lookup(db).source(db); | ||
82 | same_source(&source, &child_source) | ||
83 | }); | ||
84 | res | ||
85 | } | ||
86 | } | ||
87 | |||
88 | impl ChildFromSource<ConstId, ast::ConstDef> for TraitId { | ||
89 | fn child_from_source( | ||
90 | &self, | ||
91 | db: &impl DefDatabase, | ||
92 | child_source: InFile<ast::ConstDef>, | ||
93 | ) -> Option<ConstId> { | ||
94 | let data = db.trait_data(*self); | ||
95 | data.items | ||
96 | .iter() | ||
97 | .filter_map(|(_, item)| match item { | ||
98 | AssocItemId::ConstId(it) => Some(*it), | ||
99 | _ => None, | ||
100 | }) | ||
101 | .find(|func| { | ||
102 | let source = func.lookup(db).source(db); | ||
103 | same_source(&source, &child_source) | ||
104 | }) | ||
105 | } | ||
106 | } | ||
107 | |||
108 | impl ChildFromSource<ConstId, ast::ConstDef> for ImplId { | ||
109 | fn child_from_source( | ||
110 | &self, | ||
111 | db: &impl DefDatabase, | ||
112 | child_source: InFile<ast::ConstDef>, | ||
113 | ) -> Option<ConstId> { | ||
114 | let data = db.impl_data(*self); | ||
115 | data.items | ||
116 | .iter() | ||
117 | .filter_map(|item| match item { | ||
118 | AssocItemId::ConstId(it) => Some(*it), | ||
119 | _ => None, | ||
120 | }) | ||
121 | .find(|func| { | ||
122 | let source = func.lookup(db).source(db); | ||
123 | same_source(&source, &child_source) | ||
124 | }) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl ChildFromSource<ConstId, ast::ConstDef> for ModuleId { | ||
129 | fn child_from_source( | ||
130 | &self, | ||
131 | db: &impl DefDatabase, | ||
132 | child_source: InFile<ast::ConstDef>, | ||
133 | ) -> Option<ConstId> { | ||
134 | let crate_def_map = db.crate_def_map(self.krate); | ||
135 | let res = crate_def_map[self.local_id] | ||
136 | .scope | ||
137 | .declarations() | ||
138 | .filter_map(|item| match item { | ||
139 | ModuleDefId::ConstId(it) => Some(it), | ||
140 | _ => None, | ||
141 | }) | ||
142 | .find(|func| { | ||
143 | let source = func.lookup(db).source(db); | ||
144 | same_source(&source, &child_source) | ||
145 | }); | ||
146 | res | ||
147 | } | ||
148 | } | ||
149 | |||
150 | impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for TraitId { | ||
151 | fn child_from_source( | ||
152 | &self, | ||
153 | db: &impl DefDatabase, | ||
154 | child_source: InFile<ast::TypeAliasDef>, | ||
155 | ) -> Option<TypeAliasId> { | ||
156 | let data = db.trait_data(*self); | ||
157 | data.items | ||
158 | .iter() | ||
159 | .filter_map(|(_, item)| match item { | ||
160 | AssocItemId::TypeAliasId(it) => Some(*it), | ||
161 | _ => None, | ||
162 | }) | ||
163 | .find(|func| { | ||
164 | let source = func.lookup(db).source(db); | ||
165 | same_source(&source, &child_source) | ||
166 | }) | ||
167 | } | ||
168 | } | ||
169 | |||
170 | impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for ImplId { | ||
171 | fn child_from_source( | ||
172 | &self, | ||
173 | db: &impl DefDatabase, | ||
174 | child_source: InFile<ast::TypeAliasDef>, | ||
175 | ) -> Option<TypeAliasId> { | ||
176 | let data = db.impl_data(*self); | ||
177 | data.items | ||
178 | .iter() | ||
179 | .filter_map(|item| match item { | ||
180 | AssocItemId::TypeAliasId(it) => Some(*it), | ||
181 | _ => None, | ||
182 | }) | ||
183 | .find(|func| { | ||
184 | let source = func.lookup(db).source(db); | ||
185 | same_source(&source, &child_source) | ||
186 | }) | ||
187 | } | ||
188 | } | ||
189 | |||
190 | impl ChildFromSource<TypeAliasId, ast::TypeAliasDef> for ModuleId { | ||
191 | fn child_from_source( | ||
192 | &self, | ||
193 | db: &impl DefDatabase, | ||
194 | child_source: InFile<ast::TypeAliasDef>, | ||
195 | ) -> Option<TypeAliasId> { | ||
196 | let crate_def_map = db.crate_def_map(self.krate); | ||
197 | let res = crate_def_map[self.local_id] | ||
198 | .scope | ||
199 | .declarations() | ||
200 | .filter_map(|item| match item { | ||
201 | ModuleDefId::TypeAliasId(it) => Some(it), | ||
202 | _ => None, | ||
203 | }) | ||
204 | .find(|func| { | ||
205 | let source = func.lookup(db).source(db); | ||
206 | same_source(&source, &child_source) | ||
207 | }); | ||
208 | res | ||
209 | } | ||
210 | } | ||
211 | |||
212 | impl ChildFromSource<StaticId, ast::StaticDef> for ModuleId { | ||
213 | fn child_from_source( | ||
214 | &self, | ||
215 | db: &impl DefDatabase, | ||
216 | child_source: InFile<ast::StaticDef>, | ||
217 | ) -> Option<StaticId> { | ||
218 | let crate_def_map = db.crate_def_map(self.krate); | ||
219 | let res = crate_def_map[self.local_id] | ||
220 | .scope | ||
221 | .declarations() | ||
222 | .filter_map(|item| match item { | ||
223 | ModuleDefId::StaticId(it) => Some(it), | ||
224 | _ => None, | ||
225 | }) | ||
226 | .find(|func| { | ||
227 | let source = func.lookup(db).source(db); | ||
228 | same_source(&source, &child_source) | ||
229 | }); | ||
230 | res | ||
231 | } | ||
232 | } | ||
233 | |||
234 | impl ChildFromSource<StructFieldId, Either<ast::TupleFieldDef, ast::RecordFieldDef>> for VariantId { | ||
235 | fn child_from_source( | ||
236 | &self, | ||
237 | db: &impl DefDatabase, | ||
238 | child_source: InFile<Either<ast::TupleFieldDef, ast::RecordFieldDef>>, | ||
239 | ) -> Option<StructFieldId> { | ||
240 | let arena_map = self.child_source(db); | ||
241 | let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { | ||
242 | child_source.file_id == arena_map.file_id | ||
243 | && match (source, &child_source.value) { | ||
244 | (Either::Left(a), Either::Left(b)) => AstPtr::new(a) == AstPtr::new(b), | ||
245 | (Either::Right(a), Either::Right(b)) => AstPtr::new(a) == AstPtr::new(b), | ||
246 | _ => false, | ||
247 | } | ||
248 | })?; | ||
249 | Some(StructFieldId { parent: *self, local_id }) | ||
250 | } | ||
251 | } | ||
252 | |||
253 | impl ChildFromSource<EnumVariantId, ast::EnumVariant> for EnumId { | ||
254 | fn child_from_source( | ||
255 | &self, | ||
256 | db: &impl DefDatabase, | ||
257 | child_source: InFile<ast::EnumVariant>, | ||
258 | ) -> Option<EnumVariantId> { | ||
259 | let arena_map = self.child_source(db); | ||
260 | let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { | ||
261 | child_source.file_id == arena_map.file_id | ||
262 | && AstPtr::new(*source) == AstPtr::new(&child_source.value) | ||
263 | })?; | ||
264 | Some(EnumVariantId { parent: *self, local_id }) | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are | ||
269 | /// equal if they point to exactly the same object. | ||
270 | /// | ||
271 | /// In general, we do not guarantee that we have exactly one instance of a | ||
272 | /// syntax tree for each file. We probably should add such guarantee, but, for | ||
273 | /// the time being, we will use identity-less AstPtr comparison. | ||
274 | fn same_source<N: AstNode>(s1: &InFile<N>, s2: &InFile<N>) -> bool { | ||
275 | s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) | ||
276 | } | ||
diff --git a/crates/ra_hir_def/src/dyn_map.rs b/crates/ra_hir_def/src/dyn_map.rs new file mode 100644 index 000000000..6f269d7b0 --- /dev/null +++ b/crates/ra_hir_def/src/dyn_map.rs | |||
@@ -0,0 +1,108 @@ | |||
1 | //! This module defines a `DynMap` -- a container for heterogeneous maps. | ||
2 | //! | ||
3 | //! This means that `DynMap` stores a bunch of hash maps inside, and those maps | ||
4 | //! can be of different types. | ||
5 | //! | ||
6 | //! It is used like this: | ||
7 | //! | ||
8 | //! ``` | ||
9 | //! // keys define submaps of a `DynMap` | ||
10 | //! const STRING_TO_U32: Key<String, u32> = Key::new(); | ||
11 | //! const U32_TO_VEC: Key<u32, Vec<bool>> = Key::new(); | ||
12 | //! | ||
13 | //! // Note: concrete type, no type params! | ||
14 | //! let mut map = DynMap::new(); | ||
15 | //! | ||
16 | //! // To access a specific map, index the `DynMap` by `Key`: | ||
17 | //! map[STRING_TO_U32].insert("hello".to_string(), 92); | ||
18 | //! let value = map[U32_TO_VEC].get(92); | ||
19 | //! assert!(value.is_none()); | ||
20 | //! ``` | ||
21 | //! | ||
22 | //! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are | ||
23 | //! a coincidence. | ||
24 | use std::{ | ||
25 | hash::Hash, | ||
26 | marker::PhantomData, | ||
27 | ops::{Index, IndexMut}, | ||
28 | }; | ||
29 | |||
30 | use anymap::Map; | ||
31 | use rustc_hash::FxHashMap; | ||
32 | |||
33 | pub struct Key<K, V, P = (K, V)> { | ||
34 | _phantom: PhantomData<(K, V, P)>, | ||
35 | } | ||
36 | |||
37 | impl<K, V, P> Key<K, V, P> { | ||
38 | pub(crate) const fn new() -> Key<K, V, P> { | ||
39 | Key { _phantom: PhantomData } | ||
40 | } | ||
41 | } | ||
42 | |||
43 | impl<K, V, P> Copy for Key<K, V, P> {} | ||
44 | |||
45 | impl<K, V, P> Clone for Key<K, V, P> { | ||
46 | fn clone(&self) -> Key<K, V, P> { | ||
47 | *self | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub trait Policy { | ||
52 | type K; | ||
53 | type V; | ||
54 | |||
55 | fn insert(map: &mut DynMap, key: Self::K, value: Self::V); | ||
56 | fn get<'a>(map: &'a DynMap, key: &Self::K) -> Option<&'a Self::V>; | ||
57 | } | ||
58 | |||
59 | impl<K: Hash + Eq + 'static, V: 'static> Policy for (K, V) { | ||
60 | type K = K; | ||
61 | type V = V; | ||
62 | fn insert(map: &mut DynMap, key: K, value: V) { | ||
63 | map.map.entry::<FxHashMap<K, V>>().or_insert_with(Default::default).insert(key, value); | ||
64 | } | ||
65 | fn get<'a>(map: &'a DynMap, key: &K) -> Option<&'a V> { | ||
66 | map.map.get::<FxHashMap<K, V>>()?.get(key) | ||
67 | } | ||
68 | } | ||
69 | |||
70 | pub struct DynMap { | ||
71 | pub(crate) map: Map, | ||
72 | } | ||
73 | |||
74 | impl Default for DynMap { | ||
75 | fn default() -> Self { | ||
76 | DynMap { map: Map::new() } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | #[repr(transparent)] | ||
81 | pub struct KeyMap<KEY> { | ||
82 | map: DynMap, | ||
83 | _phantom: PhantomData<KEY>, | ||
84 | } | ||
85 | |||
86 | impl<P: Policy> KeyMap<Key<P::K, P::V, P>> { | ||
87 | pub fn insert(&mut self, key: P::K, value: P::V) { | ||
88 | P::insert(&mut self.map, key, value) | ||
89 | } | ||
90 | pub fn get(&self, key: &P::K) -> Option<&P::V> { | ||
91 | P::get(&self.map, key) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | impl<P: Policy> Index<Key<P::K, P::V, P>> for DynMap { | ||
96 | type Output = KeyMap<Key<P::K, P::V, P>>; | ||
97 | fn index(&self, _key: Key<P::K, P::V, P>) -> &Self::Output { | ||
98 | // Safe due to `#[repr(transparent)]`. | ||
99 | unsafe { std::mem::transmute::<&DynMap, &KeyMap<Key<P::K, P::V, P>>>(self) } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl<P: Policy> IndexMut<Key<P::K, P::V, P>> for DynMap { | ||
104 | fn index_mut(&mut self, _key: Key<P::K, P::V, P>) -> &mut Self::Output { | ||
105 | // Safe due to `#[repr(transparent)]`. | ||
106 | unsafe { std::mem::transmute::<&mut DynMap, &mut KeyMap<Key<P::K, P::V, P>>>(self) } | ||
107 | } | ||
108 | } | ||
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 5f648ffc3..976cf72d0 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -4,21 +4,29 @@ | |||
4 | //! in rustc. | 4 | //! in rustc. |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use hir_expand::name::{self, AsName, Name}; | 7 | use either::Either; |
8 | use hir_expand::{ | ||
9 | name::{self, AsName, Name}, | ||
10 | InFile, | ||
11 | }; | ||
12 | use ra_arena::{map::ArenaMap, Arena}; | ||
13 | use ra_db::FileId; | ||
8 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 14 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; |
9 | 15 | ||
10 | use crate::{ | 16 | use crate::{ |
17 | child_by_source::ChildBySource, | ||
11 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | dyn_map::DynMap, | ||
20 | keys, | ||
21 | src::HasChildSource, | ||
12 | src::HasSource, | 22 | src::HasSource, |
13 | type_ref::{TypeBound, TypeRef}, | 23 | type_ref::{TypeBound, TypeRef}, |
14 | AdtId, AstItemDef, ContainerId, GenericDefId, Lookup, | 24 | AdtId, AstItemDef, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, |
15 | }; | 25 | }; |
16 | 26 | ||
17 | /// Data about a generic parameter (to a function, struct, impl, ...). | 27 | /// Data about a generic parameter (to a function, struct, impl, ...). |
18 | #[derive(Clone, PartialEq, Eq, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Debug)] |
19 | pub struct GenericParam { | 29 | pub struct TypeParamData { |
20 | // FIXME: give generic params proper IDs | ||
21 | pub idx: u32, | ||
22 | pub name: Name, | 30 | pub name: Name, |
23 | pub default: Option<TypeRef>, | 31 | pub default: Option<TypeRef>, |
24 | } | 32 | } |
@@ -26,8 +34,8 @@ pub struct GenericParam { | |||
26 | /// Data about the generic parameters of a function, struct, impl, etc. | 34 | /// Data about the generic parameters of a function, struct, impl, etc. |
27 | #[derive(Clone, PartialEq, Eq, Debug)] | 35 | #[derive(Clone, PartialEq, Eq, Debug)] |
28 | pub struct GenericParams { | 36 | pub struct GenericParams { |
29 | pub parent_params: Option<Arc<GenericParams>>, | 37 | pub types: Arena<LocalTypeParamId, TypeParamData>, |
30 | pub params: Vec<GenericParam>, | 38 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, |
31 | pub where_predicates: Vec<WherePredicate>, | 39 | pub where_predicates: Vec<WherePredicate>, |
32 | } | 40 | } |
33 | 41 | ||
@@ -41,63 +49,87 @@ pub struct WherePredicate { | |||
41 | pub bound: TypeBound, | 49 | pub bound: TypeBound, |
42 | } | 50 | } |
43 | 51 | ||
52 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | ||
53 | |||
44 | impl GenericParams { | 54 | impl GenericParams { |
45 | pub(crate) fn generic_params_query( | 55 | pub(crate) fn generic_params_query( |
46 | db: &impl DefDatabase, | 56 | db: &impl DefDatabase, |
47 | def: GenericDefId, | 57 | def: GenericDefId, |
48 | ) -> Arc<GenericParams> { | 58 | ) -> Arc<GenericParams> { |
49 | let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); | 59 | let (params, _source_map) = GenericParams::new(db, def.into()); |
50 | Arc::new(GenericParams::new(db, def.into(), parent_generics)) | 60 | Arc::new(params) |
51 | } | 61 | } |
52 | 62 | ||
53 | fn new( | 63 | fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
54 | db: &impl DefDatabase, | 64 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; |
55 | def: GenericDefId, | 65 | let mut sm = ArenaMap::default(); |
56 | parent_params: Option<Arc<GenericParams>>, | ||
57 | ) -> GenericParams { | ||
58 | let mut generics = | ||
59 | GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() }; | ||
60 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
61 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 66 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
62 | match def { | 67 | let file_id = match def { |
63 | GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), | 68 | GenericDefId::FunctionId(it) => { |
64 | GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), | 69 | let src = it.lookup(db).source(db); |
65 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), | 70 | generics.fill(&mut sm, &src.value); |
66 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), | 71 | src.file_id |
72 | } | ||
73 | GenericDefId::AdtId(AdtId::StructId(it)) => { | ||
74 | let src = it.source(db); | ||
75 | generics.fill(&mut sm, &src.value); | ||
76 | src.file_id | ||
77 | } | ||
78 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | ||
79 | let src = it.source(db); | ||
80 | generics.fill(&mut sm, &src.value); | ||
81 | src.file_id | ||
82 | } | ||
83 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | ||
84 | let src = it.source(db); | ||
85 | generics.fill(&mut sm, &src.value); | ||
86 | src.file_id | ||
87 | } | ||
67 | GenericDefId::TraitId(it) => { | 88 | GenericDefId::TraitId(it) => { |
89 | let src = it.source(db); | ||
90 | |||
68 | // traits get the Self type as an implicit first type parameter | 91 | // traits get the Self type as an implicit first type parameter |
69 | generics.params.push(GenericParam { | 92 | let self_param_id = |
70 | idx: start, | 93 | generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None }); |
71 | name: name::SELF_TYPE, | 94 | sm.insert(self_param_id, Either::Left(src.value.clone())); |
72 | default: None, | ||
73 | }); | ||
74 | generics.fill(&it.source(db).value, start + 1); | ||
75 | // add super traits as bounds on Self | 95 | // add super traits as bounds on Self |
76 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 96 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
77 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | 97 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); |
78 | generics.fill_bounds(&it.source(db).value, self_param); | 98 | generics.fill_bounds(&src.value, self_param); |
99 | |||
100 | generics.fill(&mut sm, &src.value); | ||
101 | src.file_id | ||
102 | } | ||
103 | GenericDefId::TypeAliasId(it) => { | ||
104 | let src = it.lookup(db).source(db); | ||
105 | generics.fill(&mut sm, &src.value); | ||
106 | src.file_id | ||
79 | } | 107 | } |
80 | GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), | ||
81 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 108 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
82 | // type-parameter, but rather is a type-alias for impl's target | 109 | // type-parameter, but rather is a type-alias for impl's target |
83 | // type, so this is handled by the resolver. | 110 | // type, so this is handled by the resolver. |
84 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), | 111 | GenericDefId::ImplId(it) => { |
85 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} | 112 | let src = it.source(db); |
86 | } | 113 | generics.fill(&mut sm, &src.value); |
114 | src.file_id | ||
115 | } | ||
116 | // We won't be using this ID anyway | ||
117 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), | ||
118 | }; | ||
87 | 119 | ||
88 | generics | 120 | (generics, InFile::new(file_id, sm)) |
89 | } | 121 | } |
90 | 122 | ||
91 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { | 123 | fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { |
92 | if let Some(params) = node.type_param_list() { | 124 | if let Some(params) = node.type_param_list() { |
93 | self.fill_params(params, start) | 125 | self.fill_params(sm, params) |
94 | } | 126 | } |
95 | if let Some(where_clause) = node.where_clause() { | 127 | if let Some(where_clause) = node.where_clause() { |
96 | self.fill_where_predicates(where_clause); | 128 | self.fill_where_predicates(where_clause); |
97 | } | 129 | } |
98 | } | 130 | } |
99 | 131 | ||
100 | fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { | 132 | fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { |
101 | for bound in | 133 | for bound in |
102 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | 134 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) |
103 | { | 135 | { |
@@ -105,13 +137,14 @@ impl GenericParams { | |||
105 | } | 137 | } |
106 | } | 138 | } |
107 | 139 | ||
108 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | 140 | fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { |
109 | for (idx, type_param) in params.type_params().enumerate() { | 141 | for type_param in params.type_params() { |
110 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 142 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
111 | // FIXME: Use `Path::from_src` | 143 | // FIXME: Use `Path::from_src` |
112 | let default = type_param.default_type().map(TypeRef::from_ast); | 144 | let default = type_param.default_type().map(TypeRef::from_ast); |
113 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; | 145 | let param = TypeParamData { name: name.clone(), default }; |
114 | self.params.push(param); | 146 | let param_id = self.types.alloc(param); |
147 | sm.insert(param_id, Either::Right(type_param.clone())); | ||
115 | 148 | ||
116 | let type_ref = TypeRef::Path(name.into()); | 149 | let type_ref = TypeRef::Path(name.into()); |
117 | self.fill_bounds(&type_param, type_ref); | 150 | self.fill_bounds(&type_param, type_ref); |
@@ -140,45 +173,31 @@ impl GenericParams { | |||
140 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 173 | self.where_predicates.push(WherePredicate { type_ref, bound }); |
141 | } | 174 | } |
142 | 175 | ||
143 | pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 176 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
144 | self.params.iter().find(|p| &p.name == name) | 177 | self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) |
145 | } | ||
146 | |||
147 | pub fn count_parent_params(&self) -> usize { | ||
148 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
149 | } | ||
150 | |||
151 | pub fn count_params_including_parent(&self) -> usize { | ||
152 | let parent_count = self.count_parent_params(); | ||
153 | parent_count + self.params.len() | ||
154 | } | ||
155 | |||
156 | fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { | ||
157 | if let Some(parent) = &self.parent_params { | ||
158 | parent.for_each_param(f); | ||
159 | } | ||
160 | self.params.iter().for_each(f); | ||
161 | } | 178 | } |
179 | } | ||
162 | 180 | ||
163 | pub fn params_including_parent(&self) -> Vec<&GenericParam> { | 181 | impl HasChildSource for GenericDefId { |
164 | let mut vec = Vec::with_capacity(self.count_params_including_parent()); | 182 | type ChildId = LocalTypeParamId; |
165 | self.for_each_param(&mut |p| vec.push(p)); | 183 | type Value = Either<ast::TraitDef, ast::TypeParam>; |
166 | vec | 184 | fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> { |
185 | let (_, sm) = GenericParams::new(db, *self); | ||
186 | sm | ||
167 | } | 187 | } |
168 | } | 188 | } |
169 | 189 | ||
170 | fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | 190 | impl ChildBySource for GenericDefId { |
171 | let container = match def { | 191 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { |
172 | GenericDefId::FunctionId(it) => it.lookup(db).container, | 192 | let mut res = DynMap::default(); |
173 | GenericDefId::TypeAliasId(it) => it.lookup(db).container, | 193 | let arena_map = self.child_source(db); |
174 | GenericDefId::ConstId(it) => it.lookup(db).container, | 194 | let arena_map = arena_map.as_ref(); |
175 | GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), | 195 | for (local_id, src) in arena_map.value.iter() { |
176 | GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, | 196 | let id = TypeParamId { parent: *self, local_id }; |
177 | }; | 197 | if let Either::Right(type_param) = src { |
178 | 198 | res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) | |
179 | match container { | 199 | } |
180 | ContainerId::ImplId(it) => Some(it.into()), | 200 | } |
181 | ContainerId::TraitId(it) => Some(it.into()), | 201 | res |
182 | ContainerId::ModuleId(_) => None, | ||
183 | } | 202 | } |
184 | } | 203 | } |
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs new file mode 100644 index 000000000..be702a4f8 --- /dev/null +++ b/crates/ra_hir_def/src/keys.rs | |||
@@ -0,0 +1,49 @@ | |||
1 | //! keys to be used with `DynMap` | ||
2 | |||
3 | use std::marker::PhantomData; | ||
4 | |||
5 | use hir_expand::InFile; | ||
6 | use ra_syntax::{ast, AstNode, AstPtr}; | ||
7 | use rustc_hash::FxHashMap; | ||
8 | |||
9 | use crate::{ | ||
10 | dyn_map::{DynMap, Policy}, | ||
11 | ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, TypeParamId, | ||
12 | }; | ||
13 | |||
14 | type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | ||
15 | |||
16 | pub const FUNCTION: Key<ast::FnDef, FunctionId> = Key::new(); | ||
17 | pub const CONST: Key<ast::ConstDef, ConstId> = Key::new(); | ||
18 | pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new(); | ||
19 | pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new(); | ||
20 | pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new(); | ||
21 | pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new(); | ||
22 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); | ||
23 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | ||
24 | |||
25 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are | ||
26 | /// equal if they point to exactly the same object. | ||
27 | /// | ||
28 | /// In general, we do not guarantee that we have exactly one instance of a | ||
29 | /// syntax tree for each file. We probably should add such guarantee, but, for | ||
30 | /// the time being, we will use identity-less AstPtr comparison. | ||
31 | pub struct AstPtrPolicy<AST, ID> { | ||
32 | _phantom: PhantomData<(AST, ID)>, | ||
33 | } | ||
34 | |||
35 | impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> { | ||
36 | type K = InFile<AST>; | ||
37 | type V = ID; | ||
38 | fn insert(map: &mut DynMap, key: InFile<AST>, value: ID) { | ||
39 | let key = key.as_ref().map(AstPtr::new); | ||
40 | map.map | ||
41 | .entry::<FxHashMap<InFile<AstPtr<AST>>, ID>>() | ||
42 | .or_insert_with(Default::default) | ||
43 | .insert(key, value); | ||
44 | } | ||
45 | fn get<'a>(map: &'a DynMap, key: &InFile<AST>) -> Option<&'a ID> { | ||
46 | let key = key.as_ref().map(AstPtr::new); | ||
47 | map.map.get::<FxHashMap<InFile<AstPtr<AST>>, ID>>()?.get(&key) | ||
48 | } | ||
49 | } | ||
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index e02622f62..569da4f28 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -16,6 +16,9 @@ pub mod builtin_type; | |||
16 | pub mod diagnostics; | 16 | pub mod diagnostics; |
17 | pub mod per_ns; | 17 | pub mod per_ns; |
18 | 18 | ||
19 | pub mod dyn_map; | ||
20 | pub mod keys; | ||
21 | |||
19 | pub mod adt; | 22 | pub mod adt; |
20 | pub mod data; | 23 | pub mod data; |
21 | pub mod generics; | 24 | pub mod generics; |
@@ -30,7 +33,7 @@ mod trace; | |||
30 | pub mod nameres; | 33 | pub mod nameres; |
31 | 34 | ||
32 | pub mod src; | 35 | pub mod src; |
33 | pub mod child_from_source; | 36 | pub mod child_by_source; |
34 | 37 | ||
35 | #[cfg(test)] | 38 | #[cfg(test)] |
36 | mod test_db; | 39 | mod test_db; |
@@ -315,6 +318,16 @@ macro_rules! impl_froms { | |||
315 | } | 318 | } |
316 | 319 | ||
317 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 320 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
321 | pub struct TypeParamId { | ||
322 | pub parent: GenericDefId, | ||
323 | pub local_id: LocalTypeParamId, | ||
324 | } | ||
325 | |||
326 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
327 | pub struct LocalTypeParamId(RawId); | ||
328 | impl_arena_id!(LocalTypeParamId); | ||
329 | |||
330 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
318 | pub enum ContainerId { | 331 | pub enum ContainerId { |
319 | ModuleId(ModuleId), | 332 | ModuleId(ModuleId), |
320 | ImplId(ImplId), | 333 | ImplId(ImplId), |
@@ -512,6 +525,20 @@ impl HasModule for DefWithBodyId { | |||
512 | } | 525 | } |
513 | } | 526 | } |
514 | 527 | ||
528 | impl HasModule for GenericDefId { | ||
529 | fn module(&self, db: &impl db::DefDatabase) -> ModuleId { | ||
530 | match self { | ||
531 | GenericDefId::FunctionId(it) => it.lookup(db).module(db), | ||
532 | GenericDefId::AdtId(it) => it.module(db), | ||
533 | GenericDefId::TraitId(it) => it.module(db), | ||
534 | GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), | ||
535 | GenericDefId::ImplId(it) => it.module(db), | ||
536 | GenericDefId::EnumVariantId(it) => it.parent.module(db), | ||
537 | GenericDefId::ConstId(it) => it.lookup(db).module(db), | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
515 | impl HasModule for StaticLoc { | 542 | impl HasModule for StaticLoc { |
516 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { | 543 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { |
517 | self.container | 544 | self.container |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 3b3f30eec..3ff071f9e 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -7,7 +7,7 @@ use hir_expand::{ | |||
7 | builtin_derive::find_builtin_derive, | 7 | builtin_derive::find_builtin_derive, |
8 | builtin_macro::find_builtin_macro, | 8 | builtin_macro::find_builtin_macro, |
9 | name::{self, AsName, Name}, | 9 | name::{self, AsName, Name}, |
10 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, MacroFileKind, | 10 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
11 | }; | 11 | }; |
12 | use ra_cfg::CfgOptions; | 12 | use ra_cfg::CfgOptions; |
13 | use ra_db::{CrateId, FileId}; | 13 | use ra_db::{CrateId, FileId}; |
@@ -624,7 +624,7 @@ where | |||
624 | self.macro_stack_monitor.increase(macro_def_id); | 624 | self.macro_stack_monitor.increase(macro_def_id); |
625 | 625 | ||
626 | if !self.macro_stack_monitor.is_poison(macro_def_id) { | 626 | if !self.macro_stack_monitor.is_poison(macro_def_id) { |
627 | let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); | 627 | let file_id: HirFileId = macro_call_id.as_file(); |
628 | let raw_items = self.db.raw_items(file_id); | 628 | let raw_items = self.db.raw_items(file_id); |
629 | let mod_dir = self.mod_dirs[&module_id].clone(); | 629 | let mod_dir = self.mod_dirs[&module_id].clone(); |
630 | ModCollector { | 630 | ModCollector { |
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 00e866bf9..3a5105028 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs | |||
@@ -11,8 +11,6 @@ use crate::ModuleDefId; | |||
11 | pub struct PerNs { | 11 | pub struct PerNs { |
12 | pub types: Option<ModuleDefId>, | 12 | pub types: Option<ModuleDefId>, |
13 | pub values: Option<ModuleDefId>, | 13 | pub values: Option<ModuleDefId>, |
14 | /// Since macros has different type, many methods simply ignore it. | ||
15 | /// We can only use special method like `get_macros` to access it. | ||
16 | pub macros: Option<MacroDefId>, | 14 | pub macros: Option<MacroDefId>, |
17 | } | 15 | } |
18 | 16 | ||
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 7d4df222e..4c859e497 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -19,11 +19,12 @@ use crate::{ | |||
19 | per_ns::PerNs, | 19 | per_ns::PerNs, |
20 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, | 20 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, |
21 | GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, | 21 | GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, |
22 | StructId, TraitId, TypeAliasId, | 22 | StructId, TraitId, TypeAliasId, TypeParamId, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #[derive(Debug, Clone, Default)] | 25 | #[derive(Debug, Clone, Default)] |
26 | pub struct Resolver { | 26 | pub struct Resolver { |
27 | // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? | ||
27 | scopes: Vec<Scope>, | 28 | scopes: Vec<Scope>, |
28 | } | 29 | } |
29 | 30 | ||
@@ -58,7 +59,7 @@ enum Scope { | |||
58 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 59 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
59 | pub enum TypeNs { | 60 | pub enum TypeNs { |
60 | SelfType(ImplId), | 61 | SelfType(ImplId), |
61 | GenericParam(u32), | 62 | GenericParam(TypeParamId), |
62 | AdtId(AdtId), | 63 | AdtId(AdtId), |
63 | AdtSelfType(AdtId), | 64 | AdtSelfType(AdtId), |
64 | // Yup, enum variants are added to the types ns, but any usage of variant as | 65 | // Yup, enum variants are added to the types ns, but any usage of variant as |
@@ -152,10 +153,13 @@ impl Resolver { | |||
152 | Scope::ExprScope(_) => continue, | 153 | Scope::ExprScope(_) => continue, |
153 | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, | 154 | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, |
154 | 155 | ||
155 | Scope::GenericParams { params, .. } => { | 156 | Scope::GenericParams { params, def } => { |
156 | if let Some(param) = params.find_by_name(first_name) { | 157 | if let Some(local_id) = params.find_by_name(first_name) { |
157 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 158 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; |
158 | return Some((TypeNs::GenericParam(param.idx), idx)); | 159 | return Some(( |
160 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), | ||
161 | idx, | ||
162 | )); | ||
159 | } | 163 | } |
160 | } | 164 | } |
161 | Scope::ImplBlockScope(impl_) => { | 165 | Scope::ImplBlockScope(impl_) => { |
@@ -246,9 +250,9 @@ impl Resolver { | |||
246 | } | 250 | } |
247 | Scope::ExprScope(_) => continue, | 251 | Scope::ExprScope(_) => continue, |
248 | 252 | ||
249 | Scope::GenericParams { params, .. } if n_segments > 1 => { | 253 | Scope::GenericParams { params, def } if n_segments > 1 => { |
250 | if let Some(param) = params.find_by_name(first_name) { | 254 | if let Some(local_id) = params.find_by_name(first_name) { |
251 | let ty = TypeNs::GenericParam(param.idx); | 255 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); |
252 | return Some(ResolveValueResult::Partial(ty, 1)); | 256 | return Some(ResolveValueResult::Partial(ty, 1)); |
253 | } | 257 | } |
254 | } | 258 | } |
@@ -368,6 +372,7 @@ impl Resolver { | |||
368 | ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { | 372 | ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { |
369 | self.scopes | 373 | self.scopes |
370 | .iter() | 374 | .iter() |
375 | .rev() | ||
371 | .filter_map(|scope| match scope { | 376 | .filter_map(|scope| match scope { |
372 | Scope::GenericParams { params, .. } => Some(params), | 377 | Scope::GenericParams { params, .. } => Some(params), |
373 | _ => None, | 378 | _ => None, |
@@ -376,14 +381,14 @@ impl Resolver { | |||
376 | } | 381 | } |
377 | 382 | ||
378 | pub fn generic_def(&self) -> Option<GenericDefId> { | 383 | pub fn generic_def(&self) -> Option<GenericDefId> { |
379 | self.scopes.iter().find_map(|scope| match scope { | 384 | self.scopes.iter().rev().find_map(|scope| match scope { |
380 | Scope::GenericParams { def, .. } => Some(*def), | 385 | Scope::GenericParams { def, .. } => Some(*def), |
381 | _ => None, | 386 | _ => None, |
382 | }) | 387 | }) |
383 | } | 388 | } |
384 | 389 | ||
385 | pub fn body_owner(&self) -> Option<DefWithBodyId> { | 390 | pub fn body_owner(&self) -> Option<DefWithBodyId> { |
386 | self.scopes.iter().find_map(|scope| match scope { | 391 | self.scopes.iter().rev().find_map(|scope| match scope { |
387 | Scope::ExprScope(it) => Some(it.owner), | 392 | Scope::ExprScope(it) => Some(it.owner), |
388 | _ => None, | 393 | _ => None, |
389 | }) | 394 | }) |
@@ -394,7 +399,7 @@ pub enum ScopeDef { | |||
394 | PerNs(PerNs), | 399 | PerNs(PerNs), |
395 | ImplSelfType(ImplId), | 400 | ImplSelfType(ImplId), |
396 | AdtSelfType(AdtId), | 401 | AdtSelfType(AdtId), |
397 | GenericParam(u32), | 402 | GenericParam(TypeParamId), |
398 | Local(PatId), | 403 | Local(PatId), |
399 | } | 404 | } |
400 | 405 | ||
@@ -425,9 +430,12 @@ impl Scope { | |||
425 | }); | 430 | }); |
426 | } | 431 | } |
427 | } | 432 | } |
428 | Scope::GenericParams { params, .. } => { | 433 | Scope::GenericParams { params, def } => { |
429 | for param in params.params.iter() { | 434 | for (local_id, param) in params.types.iter() { |
430 | f(param.name.clone(), ScopeDef::GenericParam(param.idx)) | 435 | f( |
436 | param.name.clone(), | ||
437 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), | ||
438 | ) | ||
431 | } | 439 | } |
432 | } | 440 | } |
433 | Scope::ImplBlockScope(i) => { | 441 | Scope::ImplBlockScope(i) => { |
@@ -473,7 +481,7 @@ impl Resolver { | |||
473 | 481 | ||
474 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { | 482 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { |
475 | let params = db.generic_params(def); | 483 | let params = db.generic_params(def); |
476 | if params.params.is_empty() { | 484 | if params.types.is_empty() { |
477 | self | 485 | self |
478 | } else { | 486 | } else { |
479 | self.push_scope(Scope::GenericParams { def, params }) | 487 | self.push_scope(Scope::GenericParams { def, params }) |