diff options
Diffstat (limited to 'crates/hir_def/src/resolver.rs')
-rw-r--r-- | crates/hir_def/src/resolver.rs | 713 |
1 files changed, 713 insertions, 0 deletions
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs new file mode 100644 index 000000000..f8cc5e075 --- /dev/null +++ b/crates/hir_def/src/resolver.rs | |||
@@ -0,0 +1,713 @@ | |||
1 | //! Name resolution façade. | ||
2 | use std::sync::Arc; | ||
3 | |||
4 | use base_db::CrateId; | ||
5 | use hir_expand::{ | ||
6 | name::{name, Name}, | ||
7 | MacroDefId, | ||
8 | }; | ||
9 | use rustc_hash::FxHashSet; | ||
10 | |||
11 | use crate::{ | ||
12 | body::scope::{ExprScopes, ScopeId}, | ||
13 | body::Body, | ||
14 | builtin_type::BuiltinType, | ||
15 | db::DefDatabase, | ||
16 | expr::{ExprId, PatId}, | ||
17 | generics::GenericParams, | ||
18 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, | ||
19 | nameres::CrateDefMap, | ||
20 | path::{ModPath, PathKind}, | ||
21 | per_ns::PerNs, | ||
22 | visibility::{RawVisibility, Visibility}, | ||
23 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | ||
24 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | ||
25 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | ||
26 | }; | ||
27 | |||
28 | #[derive(Debug, Clone, Default)] | ||
29 | pub struct Resolver { | ||
30 | // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? | ||
31 | scopes: Vec<Scope>, | ||
32 | } | ||
33 | |||
34 | // FIXME how to store these best | ||
35 | #[derive(Debug, Clone)] | ||
36 | struct ModuleItemMap { | ||
37 | crate_def_map: Arc<CrateDefMap>, | ||
38 | module_id: LocalModuleId, | ||
39 | } | ||
40 | |||
41 | #[derive(Debug, Clone)] | ||
42 | struct ExprScope { | ||
43 | owner: DefWithBodyId, | ||
44 | expr_scopes: Arc<ExprScopes>, | ||
45 | scope_id: ScopeId, | ||
46 | } | ||
47 | |||
48 | #[derive(Debug, Clone)] | ||
49 | enum Scope { | ||
50 | /// All the items and imported names of a module | ||
51 | ModuleScope(ModuleItemMap), | ||
52 | /// Brings the generic parameters of an item into scope | ||
53 | GenericParams { def: GenericDefId, params: Arc<GenericParams> }, | ||
54 | /// Brings `Self` in `impl` block into scope | ||
55 | ImplDefScope(ImplId), | ||
56 | /// Brings `Self` in enum, struct and union definitions into scope | ||
57 | AdtScope(AdtId), | ||
58 | /// Local bindings | ||
59 | ExprScope(ExprScope), | ||
60 | /// Temporary hack to support local items. | ||
61 | LocalItemsScope(Arc<Body>), | ||
62 | } | ||
63 | |||
64 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
65 | pub enum TypeNs { | ||
66 | SelfType(ImplId), | ||
67 | GenericParam(TypeParamId), | ||
68 | AdtId(AdtId), | ||
69 | AdtSelfType(AdtId), | ||
70 | // Yup, enum variants are added to the types ns, but any usage of variant as | ||
71 | // type is an error. | ||
72 | EnumVariantId(EnumVariantId), | ||
73 | TypeAliasId(TypeAliasId), | ||
74 | BuiltinType(BuiltinType), | ||
75 | TraitId(TraitId), | ||
76 | // Module belong to type ns, but the resolver is used when all module paths | ||
77 | // are fully resolved. | ||
78 | // ModuleId(ModuleId) | ||
79 | } | ||
80 | |||
81 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
82 | pub enum ResolveValueResult { | ||
83 | ValueNs(ValueNs), | ||
84 | Partial(TypeNs, usize), | ||
85 | } | ||
86 | |||
87 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
88 | pub enum ValueNs { | ||
89 | ImplSelf(ImplId), | ||
90 | LocalBinding(PatId), | ||
91 | FunctionId(FunctionId), | ||
92 | ConstId(ConstId), | ||
93 | StaticId(StaticId), | ||
94 | StructId(StructId), | ||
95 | EnumVariantId(EnumVariantId), | ||
96 | } | ||
97 | |||
98 | impl Resolver { | ||
99 | /// Resolve known trait from std, like `std::futures::Future` | ||
100 | pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> { | ||
101 | let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; | ||
102 | match res { | ||
103 | ModuleDefId::TraitId(it) => Some(it), | ||
104 | _ => None, | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /// Resolve known struct from std, like `std::boxed::Box` | ||
109 | pub fn resolve_known_struct(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<StructId> { | ||
110 | let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; | ||
111 | match res { | ||
112 | ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), | ||
113 | _ => None, | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /// Resolve known enum from std, like `std::result::Result` | ||
118 | pub fn resolve_known_enum(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<EnumId> { | ||
119 | let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; | ||
120 | match res { | ||
121 | ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), | ||
122 | _ => None, | ||
123 | } | ||
124 | } | ||
125 | |||
126 | fn resolve_module_path( | ||
127 | &self, | ||
128 | db: &dyn DefDatabase, | ||
129 | path: &ModPath, | ||
130 | shadow: BuiltinShadowMode, | ||
131 | ) -> PerNs { | ||
132 | let (item_map, module) = match self.module_scope() { | ||
133 | Some(it) => it, | ||
134 | None => return PerNs::none(), | ||
135 | }; | ||
136 | let (module_res, segment_index) = item_map.resolve_path(db, module, &path, shadow); | ||
137 | if segment_index.is_some() { | ||
138 | return PerNs::none(); | ||
139 | } | ||
140 | module_res | ||
141 | } | ||
142 | |||
143 | pub fn resolve_module_path_in_items(&self, db: &dyn DefDatabase, path: &ModPath) -> PerNs { | ||
144 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) | ||
145 | } | ||
146 | |||
147 | pub fn resolve_path_in_type_ns( | ||
148 | &self, | ||
149 | db: &dyn DefDatabase, | ||
150 | path: &ModPath, | ||
151 | ) -> Option<(TypeNs, Option<usize>)> { | ||
152 | let first_name = path.segments.first()?; | ||
153 | let skip_to_mod = path.kind != PathKind::Plain; | ||
154 | for scope in self.scopes.iter().rev() { | ||
155 | match scope { | ||
156 | Scope::ExprScope(_) => continue, | ||
157 | Scope::GenericParams { .. } | ||
158 | | Scope::ImplDefScope(_) | ||
159 | | Scope::LocalItemsScope(_) | ||
160 | if skip_to_mod => | ||
161 | { | ||
162 | continue | ||
163 | } | ||
164 | |||
165 | Scope::GenericParams { params, def } => { | ||
166 | if let Some(local_id) = params.find_by_name(first_name) { | ||
167 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | ||
168 | return Some(( | ||
169 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), | ||
170 | idx, | ||
171 | )); | ||
172 | } | ||
173 | } | ||
174 | Scope::ImplDefScope(impl_) => { | ||
175 | if first_name == &name![Self] { | ||
176 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | ||
177 | return Some((TypeNs::SelfType(*impl_), idx)); | ||
178 | } | ||
179 | } | ||
180 | Scope::AdtScope(adt) => { | ||
181 | if first_name == &name![Self] { | ||
182 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | ||
183 | return Some((TypeNs::AdtSelfType(*adt), idx)); | ||
184 | } | ||
185 | } | ||
186 | Scope::ModuleScope(m) => { | ||
187 | let (module_def, idx) = m.crate_def_map.resolve_path( | ||
188 | db, | ||
189 | m.module_id, | ||
190 | &path, | ||
191 | BuiltinShadowMode::Other, | ||
192 | ); | ||
193 | let res = to_type_ns(module_def)?; | ||
194 | return Some((res, idx)); | ||
195 | } | ||
196 | Scope::LocalItemsScope(body) => { | ||
197 | let def = body.item_scope.get(first_name); | ||
198 | if let Some(res) = to_type_ns(def) { | ||
199 | return Some((res, None)); | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | return None; | ||
205 | fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> { | ||
206 | let res = match per_ns.take_types()? { | ||
207 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
208 | ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), | ||
209 | |||
210 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
211 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
212 | |||
213 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
214 | |||
215 | ModuleDefId::FunctionId(_) | ||
216 | | ModuleDefId::ConstId(_) | ||
217 | | ModuleDefId::StaticId(_) | ||
218 | | ModuleDefId::ModuleId(_) => return None, | ||
219 | }; | ||
220 | Some(res) | ||
221 | } | ||
222 | } | ||
223 | |||
224 | pub fn resolve_path_in_type_ns_fully( | ||
225 | &self, | ||
226 | db: &dyn DefDatabase, | ||
227 | path: &ModPath, | ||
228 | ) -> Option<TypeNs> { | ||
229 | let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; | ||
230 | if unresolved.is_some() { | ||
231 | return None; | ||
232 | } | ||
233 | Some(res) | ||
234 | } | ||
235 | |||
236 | pub fn resolve_visibility( | ||
237 | &self, | ||
238 | db: &dyn DefDatabase, | ||
239 | visibility: &RawVisibility, | ||
240 | ) -> Option<Visibility> { | ||
241 | match visibility { | ||
242 | RawVisibility::Module(_) => { | ||
243 | let (item_map, module) = match self.module_scope() { | ||
244 | Some(it) => it, | ||
245 | None => return None, | ||
246 | }; | ||
247 | item_map.resolve_visibility(db, module, visibility) | ||
248 | } | ||
249 | RawVisibility::Public => Some(Visibility::Public), | ||
250 | } | ||
251 | } | ||
252 | |||
253 | pub fn resolve_path_in_value_ns( | ||
254 | &self, | ||
255 | db: &dyn DefDatabase, | ||
256 | path: &ModPath, | ||
257 | ) -> Option<ResolveValueResult> { | ||
258 | let n_segments = path.segments.len(); | ||
259 | let tmp = name![self]; | ||
260 | let first_name = if path.is_self() { &tmp } else { &path.segments.first()? }; | ||
261 | let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); | ||
262 | for scope in self.scopes.iter().rev() { | ||
263 | match scope { | ||
264 | Scope::AdtScope(_) | ||
265 | | Scope::ExprScope(_) | ||
266 | | Scope::GenericParams { .. } | ||
267 | | Scope::ImplDefScope(_) | ||
268 | | Scope::LocalItemsScope(_) | ||
269 | if skip_to_mod => | ||
270 | { | ||
271 | continue | ||
272 | } | ||
273 | |||
274 | Scope::ExprScope(scope) if n_segments <= 1 => { | ||
275 | let entry = scope | ||
276 | .expr_scopes | ||
277 | .entries(scope.scope_id) | ||
278 | .iter() | ||
279 | .find(|entry| entry.name() == first_name); | ||
280 | |||
281 | if let Some(e) = entry { | ||
282 | return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat()))); | ||
283 | } | ||
284 | } | ||
285 | Scope::ExprScope(_) => continue, | ||
286 | |||
287 | Scope::GenericParams { params, def } if n_segments > 1 => { | ||
288 | if let Some(local_id) = params.find_by_name(first_name) { | ||
289 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); | ||
290 | return Some(ResolveValueResult::Partial(ty, 1)); | ||
291 | } | ||
292 | } | ||
293 | Scope::GenericParams { .. } => continue, | ||
294 | |||
295 | Scope::ImplDefScope(impl_) => { | ||
296 | if first_name == &name![Self] { | ||
297 | if n_segments > 1 { | ||
298 | let ty = TypeNs::SelfType(*impl_); | ||
299 | return Some(ResolveValueResult::Partial(ty, 1)); | ||
300 | } else { | ||
301 | return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(*impl_))); | ||
302 | } | ||
303 | } | ||
304 | } | ||
305 | Scope::AdtScope(adt) => { | ||
306 | if n_segments == 1 { | ||
307 | // bare `Self` doesn't work in the value namespace in a struct/enum definition | ||
308 | continue; | ||
309 | } | ||
310 | if first_name == &name![Self] { | ||
311 | let ty = TypeNs::AdtSelfType(*adt); | ||
312 | return Some(ResolveValueResult::Partial(ty, 1)); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | Scope::ModuleScope(m) => { | ||
317 | let (module_def, idx) = m.crate_def_map.resolve_path( | ||
318 | db, | ||
319 | m.module_id, | ||
320 | &path, | ||
321 | BuiltinShadowMode::Other, | ||
322 | ); | ||
323 | return match idx { | ||
324 | None => { | ||
325 | let value = to_value_ns(module_def)?; | ||
326 | Some(ResolveValueResult::ValueNs(value)) | ||
327 | } | ||
328 | Some(idx) => { | ||
329 | let ty = match module_def.take_types()? { | ||
330 | ModuleDefId::AdtId(it) => TypeNs::AdtId(it), | ||
331 | ModuleDefId::TraitId(it) => TypeNs::TraitId(it), | ||
332 | ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), | ||
333 | ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), | ||
334 | |||
335 | ModuleDefId::ModuleId(_) | ||
336 | | ModuleDefId::FunctionId(_) | ||
337 | | ModuleDefId::EnumVariantId(_) | ||
338 | | ModuleDefId::ConstId(_) | ||
339 | | ModuleDefId::StaticId(_) => return None, | ||
340 | }; | ||
341 | Some(ResolveValueResult::Partial(ty, idx)) | ||
342 | } | ||
343 | }; | ||
344 | } | ||
345 | Scope::LocalItemsScope(body) => { | ||
346 | // we don't bother looking in the builtin scope here because there are no builtin values | ||
347 | let def = to_value_ns(body.item_scope.get(first_name)); | ||
348 | |||
349 | if let Some(res) = def { | ||
350 | return Some(ResolveValueResult::ValueNs(res)); | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | return None; | ||
356 | |||
357 | fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { | ||
358 | let res = match per_ns.take_values()? { | ||
359 | ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), | ||
360 | ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), | ||
361 | ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), | ||
362 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | ||
363 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | ||
364 | |||
365 | ModuleDefId::AdtId(AdtId::EnumId(_)) | ||
366 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
367 | | ModuleDefId::TraitId(_) | ||
368 | | ModuleDefId::TypeAliasId(_) | ||
369 | | ModuleDefId::BuiltinType(_) | ||
370 | | ModuleDefId::ModuleId(_) => return None, | ||
371 | }; | ||
372 | Some(res) | ||
373 | } | ||
374 | } | ||
375 | |||
376 | pub fn resolve_path_in_value_ns_fully( | ||
377 | &self, | ||
378 | db: &dyn DefDatabase, | ||
379 | path: &ModPath, | ||
380 | ) -> Option<ValueNs> { | ||
381 | match self.resolve_path_in_value_ns(db, path)? { | ||
382 | ResolveValueResult::ValueNs(it) => Some(it), | ||
383 | ResolveValueResult::Partial(..) => None, | ||
384 | } | ||
385 | } | ||
386 | |||
387 | pub fn resolve_path_as_macro( | ||
388 | &self, | ||
389 | db: &dyn DefDatabase, | ||
390 | path: &ModPath, | ||
391 | ) -> Option<MacroDefId> { | ||
392 | // Search item scope legacy macro first | ||
393 | if let Some(def) = self.resolve_local_macro_def(path) { | ||
394 | return Some(def); | ||
395 | } | ||
396 | |||
397 | let (item_map, module) = self.module_scope()?; | ||
398 | item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() | ||
399 | } | ||
400 | |||
401 | pub fn process_all_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { | ||
402 | for scope in self.scopes.iter().rev() { | ||
403 | scope.process_names(db, f); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> { | ||
408 | let mut traits = FxHashSet::default(); | ||
409 | for scope in &self.scopes { | ||
410 | if let Scope::ModuleScope(m) = scope { | ||
411 | if let Some(prelude) = m.crate_def_map.prelude { | ||
412 | let prelude_def_map = db.crate_def_map(prelude.krate); | ||
413 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | ||
414 | } | ||
415 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); | ||
416 | } | ||
417 | } | ||
418 | traits | ||
419 | } | ||
420 | |||
421 | fn module_scope(&self) -> Option<(&CrateDefMap, LocalModuleId)> { | ||
422 | self.scopes.iter().rev().find_map(|scope| match scope { | ||
423 | Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), | ||
424 | |||
425 | _ => None, | ||
426 | }) | ||
427 | } | ||
428 | |||
429 | fn resolve_local_macro_def(&self, path: &ModPath) -> Option<MacroDefId> { | ||
430 | let name = path.as_ident()?; | ||
431 | self.scopes.iter().rev().find_map(|scope| { | ||
432 | if let Scope::LocalItemsScope(body) = scope { | ||
433 | return body.item_scope.get_legacy_macro(name); | ||
434 | } | ||
435 | None | ||
436 | }) | ||
437 | } | ||
438 | |||
439 | pub fn module(&self) -> Option<ModuleId> { | ||
440 | let (def_map, local_id) = self.module_scope()?; | ||
441 | Some(ModuleId { krate: def_map.krate, local_id }) | ||
442 | } | ||
443 | |||
444 | pub fn krate(&self) -> Option<CrateId> { | ||
445 | self.module_scope().map(|t| t.0.krate) | ||
446 | } | ||
447 | |||
448 | pub fn where_predicates_in_scope<'a>( | ||
449 | &'a self, | ||
450 | ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { | ||
451 | self.scopes | ||
452 | .iter() | ||
453 | .rev() | ||
454 | .filter_map(|scope| match scope { | ||
455 | Scope::GenericParams { params, .. } => Some(params), | ||
456 | _ => None, | ||
457 | }) | ||
458 | .flat_map(|params| params.where_predicates.iter()) | ||
459 | } | ||
460 | |||
461 | pub fn generic_def(&self) -> Option<GenericDefId> { | ||
462 | self.scopes.iter().rev().find_map(|scope| match scope { | ||
463 | Scope::GenericParams { def, .. } => Some(*def), | ||
464 | _ => None, | ||
465 | }) | ||
466 | } | ||
467 | |||
468 | pub fn body_owner(&self) -> Option<DefWithBodyId> { | ||
469 | self.scopes.iter().rev().find_map(|scope| match scope { | ||
470 | Scope::ExprScope(it) => Some(it.owner), | ||
471 | _ => None, | ||
472 | }) | ||
473 | } | ||
474 | } | ||
475 | |||
476 | pub enum ScopeDef { | ||
477 | PerNs(PerNs), | ||
478 | ImplSelfType(ImplId), | ||
479 | AdtSelfType(AdtId), | ||
480 | GenericParam(TypeParamId), | ||
481 | Local(PatId), | ||
482 | } | ||
483 | |||
484 | impl Scope { | ||
485 | fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { | ||
486 | match self { | ||
487 | Scope::ModuleScope(m) => { | ||
488 | // FIXME: should we provide `self` here? | ||
489 | // f( | ||
490 | // Name::self_param(), | ||
491 | // PerNs::types(Resolution::Def { | ||
492 | // def: m.module.into(), | ||
493 | // }), | ||
494 | // ); | ||
495 | m.crate_def_map[m.module_id].scope.entries().for_each(|(name, def)| { | ||
496 | f(name.clone(), ScopeDef::PerNs(def)); | ||
497 | }); | ||
498 | m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { | ||
499 | f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public))); | ||
500 | }); | ||
501 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | ||
502 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); | ||
503 | }); | ||
504 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { | ||
505 | f(name.clone(), ScopeDef::PerNs(def)); | ||
506 | }); | ||
507 | if let Some(prelude) = m.crate_def_map.prelude { | ||
508 | let prelude_def_map = db.crate_def_map(prelude.krate); | ||
509 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { | ||
510 | f(name.clone(), ScopeDef::PerNs(def)); | ||
511 | }); | ||
512 | } | ||
513 | } | ||
514 | Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| { | ||
515 | f(name.clone(), ScopeDef::PerNs(def)); | ||
516 | }), | ||
517 | Scope::GenericParams { params, def } => { | ||
518 | for (local_id, param) in params.types.iter() { | ||
519 | if let Some(name) = ¶m.name { | ||
520 | f( | ||
521 | name.clone(), | ||
522 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), | ||
523 | ) | ||
524 | } | ||
525 | } | ||
526 | } | ||
527 | Scope::ImplDefScope(i) => { | ||
528 | f(name![Self], ScopeDef::ImplSelfType(*i)); | ||
529 | } | ||
530 | Scope::AdtScope(i) => { | ||
531 | f(name![Self], ScopeDef::AdtSelfType(*i)); | ||
532 | } | ||
533 | Scope::ExprScope(scope) => { | ||
534 | scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { | ||
535 | f(e.name().clone(), ScopeDef::Local(e.pat())); | ||
536 | }); | ||
537 | } | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | // needs arbitrary_self_types to be a method... or maybe move to the def? | ||
543 | pub fn resolver_for_expr(db: &dyn DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver { | ||
544 | let scopes = db.expr_scopes(owner); | ||
545 | resolver_for_scope(db, owner, scopes.scope_for(expr_id)) | ||
546 | } | ||
547 | |||
548 | pub fn resolver_for_scope( | ||
549 | db: &dyn DefDatabase, | ||
550 | owner: DefWithBodyId, | ||
551 | scope_id: Option<ScopeId>, | ||
552 | ) -> Resolver { | ||
553 | let mut r = owner.resolver(db); | ||
554 | r = r.push_local_items_scope(db.body(owner)); | ||
555 | let scopes = db.expr_scopes(owner); | ||
556 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); | ||
557 | for scope in scope_chain.into_iter().rev() { | ||
558 | r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); | ||
559 | } | ||
560 | r | ||
561 | } | ||
562 | |||
563 | impl Resolver { | ||
564 | fn push_scope(mut self, scope: Scope) -> Resolver { | ||
565 | self.scopes.push(scope); | ||
566 | self | ||
567 | } | ||
568 | |||
569 | fn push_generic_params_scope(self, db: &dyn DefDatabase, def: GenericDefId) -> Resolver { | ||
570 | let params = db.generic_params(def); | ||
571 | self.push_scope(Scope::GenericParams { def, params }) | ||
572 | } | ||
573 | |||
574 | fn push_impl_def_scope(self, impl_def: ImplId) -> Resolver { | ||
575 | self.push_scope(Scope::ImplDefScope(impl_def)) | ||
576 | } | ||
577 | |||
578 | fn push_module_scope( | ||
579 | self, | ||
580 | crate_def_map: Arc<CrateDefMap>, | ||
581 | module_id: LocalModuleId, | ||
582 | ) -> Resolver { | ||
583 | self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) | ||
584 | } | ||
585 | |||
586 | fn push_local_items_scope(self, body: Arc<Body>) -> Resolver { | ||
587 | self.push_scope(Scope::LocalItemsScope(body)) | ||
588 | } | ||
589 | |||
590 | fn push_expr_scope( | ||
591 | self, | ||
592 | owner: DefWithBodyId, | ||
593 | expr_scopes: Arc<ExprScopes>, | ||
594 | scope_id: ScopeId, | ||
595 | ) -> Resolver { | ||
596 | self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) | ||
597 | } | ||
598 | } | ||
599 | |||
600 | pub trait HasResolver: Copy { | ||
601 | /// Builds a resolver for type references inside this def. | ||
602 | fn resolver(self, db: &dyn DefDatabase) -> Resolver; | ||
603 | } | ||
604 | |||
605 | impl HasResolver for ModuleId { | ||
606 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
607 | let def_map = db.crate_def_map(self.krate); | ||
608 | Resolver::default().push_module_scope(def_map, self.local_id) | ||
609 | } | ||
610 | } | ||
611 | |||
612 | impl HasResolver for TraitId { | ||
613 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
614 | self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) | ||
615 | } | ||
616 | } | ||
617 | |||
618 | impl<T: Into<AdtId> + Copy> HasResolver for T { | ||
619 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
620 | let def = self.into(); | ||
621 | def.module(db) | ||
622 | .resolver(db) | ||
623 | .push_generic_params_scope(db, def.into()) | ||
624 | .push_scope(Scope::AdtScope(def)) | ||
625 | } | ||
626 | } | ||
627 | |||
628 | impl HasResolver for FunctionId { | ||
629 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
630 | self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) | ||
631 | } | ||
632 | } | ||
633 | |||
634 | impl HasResolver for ConstId { | ||
635 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
636 | self.lookup(db).container.resolver(db) | ||
637 | } | ||
638 | } | ||
639 | |||
640 | impl HasResolver for StaticId { | ||
641 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
642 | self.lookup(db).container.resolver(db) | ||
643 | } | ||
644 | } | ||
645 | |||
646 | impl HasResolver for TypeAliasId { | ||
647 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
648 | self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) | ||
649 | } | ||
650 | } | ||
651 | |||
652 | impl HasResolver for ImplId { | ||
653 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
654 | self.lookup(db) | ||
655 | .container | ||
656 | .resolver(db) | ||
657 | .push_generic_params_scope(db, self.into()) | ||
658 | .push_impl_def_scope(self) | ||
659 | } | ||
660 | } | ||
661 | |||
662 | impl HasResolver for DefWithBodyId { | ||
663 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
664 | match self { | ||
665 | DefWithBodyId::ConstId(c) => c.resolver(db), | ||
666 | DefWithBodyId::FunctionId(f) => f.resolver(db), | ||
667 | DefWithBodyId::StaticId(s) => s.resolver(db), | ||
668 | } | ||
669 | } | ||
670 | } | ||
671 | |||
672 | impl HasResolver for ContainerId { | ||
673 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
674 | match self { | ||
675 | ContainerId::ModuleId(it) => it.resolver(db), | ||
676 | ContainerId::DefWithBodyId(it) => it.module(db).resolver(db), | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | |||
681 | impl HasResolver for AssocContainerId { | ||
682 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
683 | match self { | ||
684 | AssocContainerId::ContainerId(it) => it.resolver(db), | ||
685 | AssocContainerId::TraitId(it) => it.resolver(db), | ||
686 | AssocContainerId::ImplId(it) => it.resolver(db), | ||
687 | } | ||
688 | } | ||
689 | } | ||
690 | |||
691 | impl HasResolver for GenericDefId { | ||
692 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
693 | match self { | ||
694 | GenericDefId::FunctionId(inner) => inner.resolver(db), | ||
695 | GenericDefId::AdtId(adt) => adt.resolver(db), | ||
696 | GenericDefId::TraitId(inner) => inner.resolver(db), | ||
697 | GenericDefId::TypeAliasId(inner) => inner.resolver(db), | ||
698 | GenericDefId::ImplId(inner) => inner.resolver(db), | ||
699 | GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), | ||
700 | GenericDefId::ConstId(inner) => inner.resolver(db), | ||
701 | } | ||
702 | } | ||
703 | } | ||
704 | |||
705 | impl HasResolver for VariantId { | ||
706 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
707 | match self { | ||
708 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | ||
709 | VariantId::StructId(it) => it.resolver(db), | ||
710 | VariantId::UnionId(it) => it.resolver(db), | ||
711 | } | ||
712 | } | ||
713 | } | ||