aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs2
-rw-r--r--crates/ra_hir_def/src/body/scope.rs18
-rw-r--r--crates/ra_hir_def/src/lib.rs1
-rw-r--r--crates/ra_hir_def/src/marks.rs1
-rw-r--r--crates/ra_hir_def/src/resolver.rs608
-rw-r--r--crates/ra_hir_def/src/traits.rs9
6 files changed, 637 insertions, 2 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index a5bb60e85..77f091288 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -12,6 +12,7 @@ use ra_syntax::{
12 }, 12 },
13 AstNode, AstPtr, 13 AstNode, AstPtr,
14}; 14};
15use test_utils::tested_by;
15 16
16use crate::{ 17use crate::{
17 body::{Body, BodySourceMap, Expander, PatPtr}, 18 body::{Body, BodySourceMap, Expander, PatPtr},
@@ -153,6 +154,7 @@ where
153 None => self.collect_expr_opt(condition.expr()), 154 None => self.collect_expr_opt(condition.expr()),
154 // if let -- desugar to match 155 // if let -- desugar to match
155 Some(pat) => { 156 Some(pat) => {
157 tested_by!(infer_resolve_while_let);
156 let pat = self.collect_pat(pat); 158 let pat = self.collect_pat(pat);
157 let match_expr = self.collect_expr_opt(condition.expr()); 159 let match_expr = self.collect_expr_opt(condition.expr());
158 let placeholder_pat = self.missing_pat(); 160 let placeholder_pat = self.missing_pat();
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index aeb71ff22..5d7d17231 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -174,7 +174,7 @@ mod tests {
174 use hir_expand::{name::AsName, Source}; 174 use hir_expand::{name::AsName, Source};
175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; 175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase};
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, extract_offset}; 177 use test_utils::{assert_eq_text, covers, extract_offset};
178 178
179 use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId};
180 180
@@ -382,4 +382,20 @@ mod tests {
382 53, 382 53,
383 ); 383 );
384 } 384 }
385
386 #[test]
387 fn infer_resolve_while_let() {
388 covers!(infer_resolve_while_let);
389 do_check_local_name(
390 r#"
391fn test() {
392 let foo: Option<f32> = None;
393 while let Option::Some(spam) = foo {
394 spam<|>
395 }
396}
397"#,
398 75,
399 );
400 }
385} 401}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 0af41de87..d579f5c7e 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -19,6 +19,7 @@ pub mod expr;
19pub mod body; 19pub mod body;
20pub mod generics; 20pub mod generics;
21pub mod traits; 21pub mod traits;
22pub mod resolver;
22 23
23#[cfg(test)] 24#[cfg(test)]
24mod test_db; 25mod test_db;
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
index 0b99eac71..65239ca0a 100644
--- a/crates/ra_hir_def/src/marks.rs
+++ b/crates/ra_hir_def/src/marks.rs
@@ -11,4 +11,5 @@ test_utils::marks!(
11 prelude_is_macro_use 11 prelude_is_macro_use
12 macro_dollar_crate_self 12 macro_dollar_crate_self
13 macro_dollar_crate_other 13 macro_dollar_crate_other
14 infer_resolve_while_let
14); 15);
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
new file mode 100644
index 000000000..840785baa
--- /dev/null
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -0,0 +1,608 @@
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, UnionId,
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
372impl Resolver {
373 pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver {
374 self.scopes.push(scope);
375 self
376 }
377
378 pub(crate) fn push_generic_params_scope(
379 self,
380 db: &impl DefDatabase2,
381 def: GenericDefId,
382 ) -> Resolver {
383 let params = db.generic_params(def);
384 if params.params.is_empty() {
385 self
386 } else {
387 self.push_scope(Scope::GenericParams { def, params })
388 }
389 }
390
391 pub(crate) fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver {
392 self.push_scope(Scope::ImplBlockScope(impl_block))
393 }
394
395 pub(crate) fn push_module_scope(
396 self,
397 crate_def_map: Arc<CrateDefMap>,
398 module_id: CrateModuleId,
399 ) -> Resolver {
400 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
401 }
402
403 pub(crate) fn push_expr_scope(
404 self,
405 owner: DefWithBodyId,
406 expr_scopes: Arc<ExprScopes>,
407 scope_id: ScopeId,
408 ) -> Resolver {
409 self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id }))
410 }
411}
412
413pub enum ScopeDef {
414 PerNs(PerNs),
415 ImplSelfType(ImplId),
416 AdtSelfType(AdtId),
417 GenericParam(u32),
418 Local(PatId),
419}
420
421impl Scope {
422 fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) {
423 match self {
424 Scope::ModuleScope(m) => {
425 // FIXME: should we provide `self` here?
426 // f(
427 // Name::self_param(),
428 // PerNs::types(Resolution::Def {
429 // def: m.module.into(),
430 // }),
431 // );
432 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| {
433 f(name.clone(), ScopeDef::PerNs(res.def));
434 });
435 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
436 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_)));
437 });
438 m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| {
439 f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into())));
440 });
441 if let Some(prelude) = m.crate_def_map.prelude() {
442 let prelude_def_map = db.crate_def_map(prelude.krate);
443 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
444 f(name.clone(), ScopeDef::PerNs(res.def));
445 });
446 }
447 }
448 Scope::GenericParams { params, .. } => {
449 for param in params.params.iter() {
450 f(param.name.clone(), ScopeDef::GenericParam(param.idx))
451 }
452 }
453 Scope::ImplBlockScope(i) => {
454 f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into()));
455 }
456 Scope::AdtScope(i) => {
457 f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into()));
458 }
459 Scope::ExprScope(scope) => {
460 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
461 f(e.name().clone(), ScopeDef::Local(e.pat()));
462 });
463 }
464 }
465 }
466}
467
468// needs arbitrary_self_types to be a method... or maybe move to the def?
469pub fn resolver_for_expr(
470 db: &impl DefDatabase2,
471 owner: DefWithBodyId,
472 expr_id: ExprId,
473) -> Resolver {
474 let scopes = db.expr_scopes(owner);
475 resolver_for_scope(db, owner, scopes.scope_for(expr_id))
476}
477
478pub fn resolver_for_scope(
479 db: &impl DefDatabase2,
480 owner: DefWithBodyId,
481 scope_id: Option<ScopeId>,
482) -> Resolver {
483 let mut r = owner.resolver(db);
484 let scopes = db.expr_scopes(owner);
485 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
486 for scope in scope_chain.into_iter().rev() {
487 r = r.push_expr_scope(owner, Arc::clone(&scopes), scope);
488 }
489 r
490}
491
492pub trait HasResolver {
493 /// Builds a resolver for type references inside this def.
494 fn resolver(self, db: &impl DefDatabase2) -> Resolver;
495}
496
497impl HasResolver for ModuleId {
498 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
499 let def_map = db.crate_def_map(self.krate);
500 Resolver::default().push_module_scope(def_map, self.module_id)
501 }
502}
503
504impl HasResolver for TraitId {
505 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
506 self.module(db).resolver(db).push_generic_params_scope(db, self.into())
507 }
508}
509
510impl HasResolver for AdtId {
511 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
512 let module = match self {
513 AdtId::StructId(it) => it.0.module(db),
514 AdtId::UnionId(it) => it.0.module(db),
515 AdtId::EnumId(it) => it.module(db),
516 };
517
518 module
519 .resolver(db)
520 .push_generic_params_scope(db, self.into())
521 .push_scope(Scope::AdtScope(self.into()))
522 }
523}
524
525impl HasResolver for StructId {
526 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
527 AdtId::from(self).resolver(db)
528 }
529}
530
531impl HasResolver for UnionId {
532 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
533 AdtId::from(self).resolver(db)
534 }
535}
536
537impl HasResolver for EnumId {
538 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
539 AdtId::from(self).resolver(db)
540 }
541}
542
543impl HasResolver for FunctionId {
544 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
545 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
546 }
547}
548
549impl HasResolver for DefWithBodyId {
550 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
551 match self {
552 DefWithBodyId::ConstId(c) => c.resolver(db),
553 DefWithBodyId::FunctionId(f) => f.resolver(db),
554 DefWithBodyId::StaticId(s) => s.resolver(db),
555 }
556 }
557}
558
559impl HasResolver for ConstId {
560 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
561 self.lookup(db).container.resolver(db)
562 }
563}
564
565impl HasResolver for StaticId {
566 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
567 self.module(db).resolver(db)
568 }
569}
570
571impl HasResolver for TypeAliasId {
572 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
573 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
574 }
575}
576
577impl HasResolver for ContainerId {
578 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
579 match self {
580 ContainerId::TraitId(it) => it.resolver(db),
581 ContainerId::ImplId(it) => it.resolver(db),
582 ContainerId::ModuleId(it) => it.resolver(db),
583 }
584 }
585}
586
587impl HasResolver for GenericDefId {
588 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
589 match self {
590 GenericDefId::FunctionId(inner) => inner.resolver(db),
591 GenericDefId::AdtId(adt) => adt.resolver(db),
592 GenericDefId::TraitId(inner) => inner.resolver(db),
593 GenericDefId::TypeAliasId(inner) => inner.resolver(db),
594 GenericDefId::ImplId(inner) => inner.resolver(db),
595 GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db),
596 GenericDefId::ConstId(inner) => inner.resolver(db),
597 }
598 }
599}
600
601impl HasResolver for ImplId {
602 fn resolver(self, db: &impl DefDatabase2) -> Resolver {
603 self.module(db)
604 .resolver(db)
605 .push_generic_params_scope(db, self.into())
606 .push_impl_block_scope(self)
607 }
608}
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
index 877d73d66..6c2d5b2a9 100644
--- a/crates/ra_hir_def/src/traits.rs
+++ b/crates/ra_hir_def/src/traits.rs
@@ -11,7 +11,7 @@ use ra_syntax::ast::{self, NameOwner};
11 11
12use crate::{ 12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId, 13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasLoc, 14 TypeAliasId, TypeAliasLoc,
15}; 15};
16 16
17#[derive(Debug, Clone, PartialEq, Eq)] 17#[derive(Debug, Clone, PartialEq, Eq)]
@@ -56,4 +56,11 @@ impl TraitData {
56 }; 56 };
57 Arc::new(TraitData { name, items, auto }) 57 Arc::new(TraitData { name, items, auto })
58 } 58 }
59
60 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
61 self.items.iter().filter_map(|item| match item {
62 AssocItemId::TypeAliasId(t) => Some(*t),
63 _ => None,
64 })
65 }
59} 66}