diff options
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 57 |
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)] |
42 | pub struct CrateImplDefs { | 43 | pub 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 | ||
47 | impl CrateImplDefs { | 48 | impl 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() |