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