diff options
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 74a0bc7db..657284fd0 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -34,7 +34,7 @@ impl TyFingerprint { | |||
34 | /// Creates a TyFingerprint for looking up an impl. Only certain types can | 34 | /// Creates a TyFingerprint for looking up an impl. Only certain types can |
35 | /// have impls: if we have some `struct S`, we can have an `impl S`, but not | 35 | /// have impls: if we have some `struct S`, we can have an `impl S`, but not |
36 | /// `impl &S`. Hence, this will return `None` for reference types and such. | 36 | /// `impl &S`. Hence, this will return `None` for reference types and such. |
37 | fn for_impl(ty: &Ty) -> Option<TyFingerprint> { | 37 | pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { |
38 | match ty { | 38 | match ty { |
39 | Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), | 39 | Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), |
40 | _ => None, | 40 | _ => None, |
@@ -45,7 +45,7 @@ impl TyFingerprint { | |||
45 | #[derive(Debug, PartialEq, Eq)] | 45 | #[derive(Debug, PartialEq, Eq)] |
46 | pub struct CrateImplDefs { | 46 | pub struct CrateImplDefs { |
47 | impls: FxHashMap<TyFingerprint, Vec<ImplId>>, | 47 | impls: FxHashMap<TyFingerprint, Vec<ImplId>>, |
48 | impls_by_trait: FxHashMap<TraitId, Vec<ImplId>>, | 48 | impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, |
49 | } | 49 | } |
50 | 50 | ||
51 | impl CrateImplDefs { | 51 | impl CrateImplDefs { |
@@ -59,7 +59,14 @@ impl CrateImplDefs { | |||
59 | for impl_id in module_data.scope.impls() { | 59 | for impl_id in module_data.scope.impls() { |
60 | match db.impl_trait(impl_id) { | 60 | match db.impl_trait(impl_id) { |
61 | Some(tr) => { | 61 | Some(tr) => { |
62 | res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id); | 62 | let self_ty = db.impl_self_ty(impl_id); |
63 | let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); | ||
64 | res.impls_by_trait | ||
65 | .entry(tr.value.trait_) | ||
66 | .or_default() | ||
67 | .entry(self_ty_fp) | ||
68 | .or_default() | ||
69 | .push(impl_id); | ||
63 | } | 70 | } |
64 | None => { | 71 | None => { |
65 | let self_ty = db.impl_self_ty(impl_id); | 72 | let self_ty = db.impl_self_ty(impl_id); |
@@ -79,11 +86,39 @@ impl CrateImplDefs { | |||
79 | } | 86 | } |
80 | 87 | ||
81 | pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { | 88 | pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { |
82 | self.impls_by_trait.get(&tr).into_iter().flatten().copied() | 89 | self.impls_by_trait |
90 | .get(&tr) | ||
91 | .into_iter() | ||
92 | .flat_map(|m| m.values().flat_map(|v| v.iter().copied())) | ||
93 | } | ||
94 | |||
95 | pub fn lookup_impl_defs_for_trait_and_ty( | ||
96 | &self, | ||
97 | tr: TraitId, | ||
98 | fp: TyFingerprint, | ||
99 | ) -> impl Iterator<Item = ImplId> + '_ { | ||
100 | self.impls_by_trait | ||
101 | .get(&tr) | ||
102 | .and_then(|m| m.get(&Some(fp))) | ||
103 | .into_iter() | ||
104 | .flatten() | ||
105 | .copied() | ||
106 | .chain( | ||
107 | self.impls_by_trait | ||
108 | .get(&tr) | ||
109 | .and_then(|m| m.get(&None)) | ||
110 | .into_iter() | ||
111 | .flatten() | ||
112 | .copied(), | ||
113 | ) | ||
83 | } | 114 | } |
84 | 115 | ||
85 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { | 116 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { |
86 | self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() | 117 | self.impls |
118 | .values() | ||
119 | .chain(self.impls_by_trait.values().flat_map(|m| m.values())) | ||
120 | .flatten() | ||
121 | .copied() | ||
87 | } | 122 | } |
88 | } | 123 | } |
89 | 124 | ||