diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index ee0c7b00f..332bb14b2 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -191,27 +191,48 @@ pub(crate) fn iterate_method_candidates<T>( | |||
191 | mode: LookupMode, | 191 | mode: LookupMode, |
192 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 192 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
193 | ) -> Option<T> { | 193 | ) -> Option<T> { |
194 | // For method calls, rust first does any number of autoderef, and then one | 194 | let krate = resolver.krate()?; |
195 | // autoref (i.e. when the method takes &self or &mut self). We just ignore | 195 | match mode { |
196 | // the autoref currently -- when we find a method matching the given name, | 196 | LookupMode::MethodCall => { |
197 | // we assume it fits. | 197 | // For method calls, rust first does any number of autoderef, and then one |
198 | // autoref (i.e. when the method takes &self or &mut self). We just ignore | ||
199 | // the autoref currently -- when we find a method matching the given name, | ||
200 | // we assume it fits. | ||
198 | 201 | ||
199 | // Also note that when we've got a receiver like &S, even if the method we | 202 | // Also note that when we've got a receiver like &S, even if the method we |
200 | // find in the end takes &self, we still do the autoderef step (just as | 203 | // find in the end takes &self, we still do the autoderef step (just as |
201 | // rustc does an autoderef and then autoref again). | 204 | // rustc does an autoderef and then autoref again). |
202 | 205 | ||
203 | let krate = resolver.krate()?; | 206 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { |
204 | // TODO no autoderef in LookupMode::Path | 207 | if let Some(result) = |
205 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { | 208 | iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback) |
206 | if let Some(result) = | 209 | { |
207 | iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback) | 210 | return Some(result); |
208 | { | 211 | } |
209 | return Some(result); | 212 | if let Some(result) = iterate_trait_method_candidates( |
213 | &derefed_ty, | ||
214 | db, | ||
215 | resolver, | ||
216 | name, | ||
217 | mode, | ||
218 | &mut callback, | ||
219 | ) { | ||
220 | return Some(result); | ||
221 | } | ||
222 | } | ||
210 | } | 223 | } |
211 | if let Some(result) = | 224 | LookupMode::Path => { |
212 | iterate_trait_method_candidates(&derefed_ty, db, resolver, name, mode, &mut callback) | 225 | // No autoderef for path lookups |
213 | { | 226 | if let Some(result) = |
214 | return Some(result); | 227 | iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback) |
228 | { | ||
229 | return Some(result); | ||
230 | } | ||
231 | if let Some(result) = | ||
232 | iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback) | ||
233 | { | ||
234 | return Some(result); | ||
235 | } | ||
215 | } | 236 | } |
216 | } | 237 | } |
217 | None | 238 | None |