aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs57
1 files changed, 48 insertions, 9 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index e83b39456..01b3362d7 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -38,18 +38,58 @@ impl TyFingerprint {
38 } 38 }
39} 39}
40 40
41/// A queryable and mergeable collection of impls.
41#[derive(Debug, PartialEq, Eq)] 42#[derive(Debug, PartialEq, Eq)]
42pub struct CrateImplDefs { 43pub struct CrateImplDefs {
43 impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 44 inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
44 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, 45 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
45} 46}
46 47
47impl CrateImplDefs { 48impl CrateImplDefs {
48 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { 49 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
49 let _p = profile("impls_in_crate_query"); 50 let _p = profile("impls_in_crate_query");
50 let mut res = 51 let mut res = CrateImplDefs {
51 CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; 52 inherent_impls: FxHashMap::default(),
53 impls_by_trait: FxHashMap::default(),
54 };
55 res.fill(db, krate);
56
57 Arc::new(res)
58 }
59
60 /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61 ///
62 /// The full set of impls that can be used by `krate` is the returned map plus all the impls
63 /// from `krate` itself.
64 pub(crate) fn impls_from_deps_query(
65 db: &dyn HirDatabase,
66 krate: CrateId,
67 ) -> Arc<CrateImplDefs> {
68 // FIXME: This should take visibility and orphan rules into account to keep the result
69 // smaller.
70 let _p = profile("impls_from_deps_query");
71 let crate_graph = db.crate_graph();
72 let mut res = CrateImplDefs {
73 inherent_impls: FxHashMap::default(),
74 impls_by_trait: FxHashMap::default(),
75 };
76 let mut seen = FxHashSet::default();
77 let mut worklist = vec![krate];
78 while let Some(krate) = worklist.pop() {
79 if !seen.insert(krate) {
80 continue;
81 }
52 82
83 // No deduplication, since a) impls can't be reexported, b) we visit a crate only once
84 res.fill(db, krate);
85
86 worklist.extend(crate_graph[krate].dependencies.iter().map(|dep| dep.crate_id));
87 }
88
89 Arc::new(res)
90 }
91
92 fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
53 let crate_def_map = db.crate_def_map(krate); 93 let crate_def_map = db.crate_def_map(krate);
54 for (_module_id, module_data) in crate_def_map.modules.iter() { 94 for (_module_id, module_data) in crate_def_map.modules.iter() {
55 for impl_id in module_data.scope.impls() { 95 for impl_id in module_data.scope.impls() {
@@ -57,7 +97,7 @@ impl CrateImplDefs {
57 Some(tr) => { 97 Some(tr) => {
58 let self_ty = db.impl_self_ty(impl_id); 98 let self_ty = db.impl_self_ty(impl_id);
59 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); 99 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
60 res.impls_by_trait 100 self.impls_by_trait
61 .entry(tr.value.trait_) 101 .entry(tr.value.trait_)
62 .or_default() 102 .or_default()
63 .entry(self_ty_fp) 103 .entry(self_ty_fp)
@@ -67,18 +107,17 @@ impl CrateImplDefs {
67 None => { 107 None => {
68 let self_ty = db.impl_self_ty(impl_id); 108 let self_ty = db.impl_self_ty(impl_id);
69 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { 109 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
70 res.impls.entry(self_ty_fp).or_default().push(impl_id); 110 self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
71 } 111 }
72 } 112 }
73 } 113 }
74 } 114 }
75 } 115 }
76
77 Arc::new(res)
78 } 116 }
117
79 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 118 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
80 let fingerprint = TyFingerprint::for_impl(ty); 119 let fingerprint = TyFingerprint::for_impl(ty);
81 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 120 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
82 } 121 }
83 122
84 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { 123 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -110,7 +149,7 @@ impl CrateImplDefs {
110 } 149 }
111 150
112 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 151 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
113 self.impls 152 self.inherent_impls
114 .values() 153 .values()
115 .chain(self.impls_by_trait.values().flat_map(|m| m.values())) 154 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
116 .flatten() 155 .flatten()