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