aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/method_resolution.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-26 12:42:15 +0000
committerGitHub <[email protected]>2019-11-26 12:42:15 +0000
commit36dca8de93c07be62724f973aa4c8a045941d218 (patch)
treedbe3d521c869aa12c922098e9544859343494a0e /crates/ra_hir/src/ty/method_resolution.rs
parent280946e597f880709d2dc2e12eb9a6db3223d979 (diff)
parent4e17718a9aaba34533ba6a46d52b4aa959c662c7 (diff)
Merge #2410
2410: Introduce hir_ty r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs101
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 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef, HasModule}; 8use hir_def::{
9 lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, AssocItemId, AstItemDef,
10 HasModule, ImplId, TraitId,
11};
12use ra_db::CrateId;
13use ra_prof::profile;
9use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
10 15
11use crate::{ 16use 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
18use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 23use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
@@ -37,54 +42,58 @@ impl TyFingerprint {
37 42
38#[derive(Debug, PartialEq, Eq)] 43#[derive(Debug, PartialEq, Eq)]
39pub struct CrateImplBlocks { 44pub 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
44impl CrateImplBlocks { 49impl 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
90fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { 99fn 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 }