diff options
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 101 |
1 files changed, 55 insertions, 46 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 7f0ff2e8c..489fcd64b 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -5,14 +5,19 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef, HasModule}; | 8 | use hir_def::{ |
9 | lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, AssocItemId, AstItemDef, | ||
10 | HasModule, ImplId, TraitId, | ||
11 | }; | ||
12 | use ra_db::CrateId; | ||
13 | use ra_prof::profile; | ||
9 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
10 | 15 | ||
11 | use crate::{ | 16 | use crate::{ |
12 | db::HirDatabase, | 17 | db::HirDatabase, |
13 | ty::primitive::{FloatBitness, Uncertain}, | 18 | ty::primitive::{FloatBitness, Uncertain}, |
14 | ty::{Ty, TypeCtor}, | 19 | ty::{Ty, TypeCtor}, |
15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, | 20 | AssocItem, Crate, Function, Mutability, Name, Trait, |
16 | }; | 21 | }; |
17 | 22 | ||
18 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 23 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
@@ -37,54 +42,58 @@ impl TyFingerprint { | |||
37 | 42 | ||
38 | #[derive(Debug, PartialEq, Eq)] | 43 | #[derive(Debug, PartialEq, Eq)] |
39 | pub struct CrateImplBlocks { | 44 | pub struct CrateImplBlocks { |
40 | impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>, | 45 | impls: FxHashMap<TyFingerprint, Vec<ImplId>>, |
41 | impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>, | 46 | impls_by_trait: FxHashMap<TraitId, Vec<ImplId>>, |
42 | } | 47 | } |
43 | 48 | ||
44 | impl CrateImplBlocks { | 49 | impl CrateImplBlocks { |
45 | pub(crate) fn impls_in_crate_query( | 50 | pub(crate) fn impls_in_crate_query( |
46 | db: &impl HirDatabase, | 51 | db: &impl HirDatabase, |
47 | krate: Crate, | 52 | krate: CrateId, |
48 | ) -> Arc<CrateImplBlocks> { | 53 | ) -> Arc<CrateImplBlocks> { |
49 | let mut crate_impl_blocks = | 54 | let _p = profile("impls_in_crate_query"); |
55 | let mut res = | ||
50 | CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; | 56 | CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; |
51 | if let Some(module) = krate.root_module(db) { | 57 | |
52 | crate_impl_blocks.collect_recursive(db, module); | 58 | let crate_def_map = db.crate_def_map(krate); |
59 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
60 | for &impl_id in module_data.impls.iter() { | ||
61 | let impl_data = db.impl_data(impl_id); | ||
62 | let resolver = impl_id.resolver(db); | ||
63 | |||
64 | let target_ty = { Ty::from_hir(db, &resolver, &impl_data.target_type) }; | ||
65 | |||
66 | match &impl_data.target_trait { | ||
67 | Some(trait_ref) => { | ||
68 | if let Some(tr) = | ||
69 | TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)) | ||
70 | { | ||
71 | res.impls_by_trait.entry(tr.trait_.id).or_default().push(impl_id); | ||
72 | } | ||
73 | } | ||
74 | None => { | ||
75 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | ||
76 | res.impls.entry(target_ty_fp).or_default().push(impl_id); | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | } | ||
53 | } | 81 | } |
54 | Arc::new(crate_impl_blocks) | 82 | |
83 | Arc::new(res) | ||
55 | } | 84 | } |
56 | pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + '_ { | 85 | pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { |
57 | let fingerprint = TyFingerprint::for_impl(ty); | 86 | let fingerprint = TyFingerprint::for_impl(ty); |
58 | fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() | 87 | fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() |
59 | } | 88 | } |
60 | 89 | ||
61 | pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ { | 90 | pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplId> + '_ { |
62 | self.impls_by_trait.get(&tr).into_iter().flatten().copied() | 91 | self.impls_by_trait.get(&tr.id).into_iter().flatten().copied() |
63 | } | 92 | } |
64 | 93 | ||
65 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { | 94 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { |
66 | self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() | 95 | self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() |
67 | } | 96 | } |
68 | |||
69 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { | ||
70 | for impl_block in module.impl_blocks(db) { | ||
71 | let target_ty = impl_block.target_ty(db); | ||
72 | |||
73 | if impl_block.target_trait(db).is_some() { | ||
74 | if let Some(tr) = impl_block.target_trait_ref(db) { | ||
75 | self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block); | ||
76 | } | ||
77 | } else { | ||
78 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | ||
79 | self.impls.entry(target_ty_fp).or_default().push(impl_block); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | for child in module.children(db) { | ||
85 | self.collect_recursive(db, child); | ||
86 | } | ||
87 | } | ||
88 | } | 97 | } |
89 | 98 | ||
90 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { | 99 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { |
@@ -279,14 +288,14 @@ fn iterate_inherent_methods<T>( | |||
279 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 288 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
280 | ) -> Option<T> { | 289 | ) -> Option<T> { |
281 | for krate in def_crates(db, krate, &ty.value)? { | 290 | for krate in def_crates(db, krate, &ty.value)? { |
282 | let impls = db.impls_in_crate(krate); | 291 | let impls = db.impls_in_crate(krate.crate_id); |
283 | 292 | ||
284 | for impl_block in impls.lookup_impl_blocks(&ty.value) { | 293 | for impl_block in impls.lookup_impl_blocks(&ty.value) { |
285 | for item in impl_block.items(db) { | 294 | for &item in db.impl_data(impl_block).items.iter() { |
286 | if !is_valid_candidate(db, name, mode, item) { | 295 | if !is_valid_candidate(db, name, mode, item) { |
287 | continue; | 296 | continue; |
288 | } | 297 | } |
289 | if let Some(result) = callback(&ty.value, item) { | 298 | if let Some(result) = callback(&ty.value, item.into()) { |
290 | return Some(result); | 299 | return Some(result); |
291 | } | 300 | } |
292 | } | 301 | } |
@@ -299,17 +308,17 @@ fn is_valid_candidate( | |||
299 | db: &impl HirDatabase, | 308 | db: &impl HirDatabase, |
300 | name: Option<&Name>, | 309 | name: Option<&Name>, |
301 | mode: LookupMode, | 310 | mode: LookupMode, |
302 | item: AssocItem, | 311 | item: AssocItemId, |
303 | ) -> bool { | 312 | ) -> bool { |
304 | match item { | 313 | match item { |
305 | AssocItem::Function(m) => { | 314 | AssocItemId::FunctionId(m) => { |
306 | let data = db.function_data(m.id); | 315 | let data = db.function_data(m); |
307 | name.map_or(true, |name| data.name == *name) | 316 | name.map_or(true, |name| &data.name == name) |
308 | && (data.has_self_param || mode == LookupMode::Path) | 317 | && (data.has_self_param || mode == LookupMode::Path) |
309 | } | 318 | } |
310 | AssocItem::Const(c) => { | 319 | AssocItemId::ConstId(c) => { |
311 | name.map_or(true, |name| Some(name) == c.name(db).as_ref()) | 320 | let data = db.const_data(c); |
312 | && (mode == LookupMode::Path) | 321 | name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path) |
313 | } | 322 | } |
314 | _ => false, | 323 | _ => false, |
315 | } | 324 | } |
@@ -344,11 +353,11 @@ impl Ty { | |||
344 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 353 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
345 | ) -> Option<T> { | 354 | ) -> Option<T> { |
346 | for krate in def_crates(db, krate, &self)? { | 355 | for krate in def_crates(db, krate, &self)? { |
347 | let impls = db.impls_in_crate(krate); | 356 | let impls = db.impls_in_crate(krate.crate_id); |
348 | 357 | ||
349 | for impl_block in impls.lookup_impl_blocks(&self) { | 358 | for impl_block in impls.lookup_impl_blocks(&self) { |
350 | for item in impl_block.items(db) { | 359 | for &item in db.impl_data(impl_block).items.iter() { |
351 | if let Some(result) = callback(item) { | 360 | if let Some(result) = callback(item.into()) { |
352 | return Some(result); | 361 | return Some(result); |
353 | } | 362 | } |
354 | } | 363 | } |