diff options
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index b1684acf9..708a435b4 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | ids::TraitId, | 11 | ids::TraitId, |
12 | impl_block::{ImplId, ImplBlock, ImplItem}, | 12 | impl_block::{ImplId, ImplBlock, ImplItem}, |
13 | ty::{Ty, TypeCtor}, | 13 | ty::{Ty, TypeCtor}, |
14 | nameres::CrateModuleId, | 14 | nameres::CrateModuleId, resolve::Resolver, traits::TraitItem |
15 | 15 | ||
16 | }; | 16 | }; |
17 | 17 | ||
@@ -73,18 +73,18 @@ impl CrateImplBlocks { | |||
73 | 73 | ||
74 | let target_ty = impl_block.target_ty(db); | 74 | let target_ty = impl_block.target_ty(db); |
75 | 75 | ||
76 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | ||
77 | self.impls | ||
78 | .entry(target_ty_fp) | ||
79 | .or_insert_with(Vec::new) | ||
80 | .push((module.module_id, impl_id)); | ||
81 | } | ||
82 | |||
83 | if let Some(tr) = impl_block.target_trait(db) { | 76 | if let Some(tr) = impl_block.target_trait(db) { |
84 | self.impls_by_trait | 77 | self.impls_by_trait |
85 | .entry(tr.id) | 78 | .entry(tr.id) |
86 | .or_insert_with(Vec::new) | 79 | .or_insert_with(Vec::new) |
87 | .push((module.module_id, impl_id)); | 80 | .push((module.module_id, impl_id)); |
81 | } else { | ||
82 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | ||
83 | self.impls | ||
84 | .entry(target_ty_fp) | ||
85 | .or_insert_with(Vec::new) | ||
86 | .push((module.module_id, impl_id)); | ||
87 | } | ||
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
@@ -120,20 +120,52 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { | |||
120 | } | 120 | } |
121 | 121 | ||
122 | impl Ty { | 122 | impl Ty { |
123 | // FIXME: cache this as a query? | ||
124 | // - if so, what signature? (TyFingerprint, Name)? | ||
125 | // - or maybe cache all names and def_ids of methods per fingerprint? | ||
126 | /// Look up the method with the given name, returning the actual autoderefed | 123 | /// Look up the method with the given name, returning the actual autoderefed |
127 | /// receiver type (but without autoref applied yet). | 124 | /// receiver type (but without autoref applied yet). |
128 | pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> { | 125 | pub fn lookup_method( |
129 | self.iterate_methods(db, |ty, f| { | 126 | self, |
127 | db: &impl HirDatabase, | ||
128 | name: &Name, | ||
129 | resolver: &Resolver, | ||
130 | ) -> Option<(Ty, Function)> { | ||
131 | // FIXME: what has priority, an inherent method that needs autoderefs or a trait method? | ||
132 | let inherent_method = self.clone().iterate_methods(db, |ty, f| { | ||
130 | let sig = f.signature(db); | 133 | let sig = f.signature(db); |
131 | if sig.name() == name && sig.has_self_param() { | 134 | if sig.name() == name && sig.has_self_param() { |
132 | Some((ty.clone(), f)) | 135 | Some((ty.clone(), f)) |
133 | } else { | 136 | } else { |
134 | None | 137 | None |
135 | } | 138 | } |
136 | }) | 139 | }); |
140 | inherent_method.or_else(|| self.lookup_trait_method(db, name, resolver)) | ||
141 | } | ||
142 | |||
143 | fn lookup_trait_method( | ||
144 | self, | ||
145 | db: &impl HirDatabase, | ||
146 | name: &Name, | ||
147 | resolver: &Resolver, | ||
148 | ) -> Option<(Ty, Function)> { | ||
149 | let mut candidates = Vec::new(); | ||
150 | for t in resolver.traits_in_scope() { | ||
151 | let data = t.trait_data(db); | ||
152 | for item in data.items() { | ||
153 | match item { | ||
154 | &TraitItem::Function(m) => { | ||
155 | let sig = m.signature(db); | ||
156 | if sig.name() == name && sig.has_self_param() { | ||
157 | candidates.push((t, m)); | ||
158 | } | ||
159 | } | ||
160 | _ => {} | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | // FIXME the implements check may result in other obligations or unifying variables? | ||
165 | candidates.retain(|(_t, _m)| /* self implements t */ true); | ||
166 | // FIXME what happens if there are still multiple potential candidates? | ||
167 | let (_chosen_trait, chosen_method) = candidates.first()?; | ||
168 | Some((self.clone(), *chosen_method)) | ||
137 | } | 169 | } |
138 | 170 | ||
139 | // This would be nicer if it just returned an iterator, but that runs into | 171 | // This would be nicer if it just returned an iterator, but that runs into |