diff options
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 55435e6ea..e43fadf20 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -12,7 +12,7 @@ use hir_def::{ | |||
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | 16 | ||
17 | use super::Substs; | 17 | use super::Substs; |
18 | use crate::{ | 18 | use crate::{ |
@@ -177,6 +177,9 @@ pub fn iterate_method_candidates<T>( | |||
177 | mode: LookupMode, | 177 | mode: LookupMode, |
178 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 178 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
179 | ) -> Option<T> { | 179 | ) -> Option<T> { |
180 | let traits_in_scope = resolver.traits_in_scope(db); | ||
181 | let krate = resolver.krate()?; | ||
182 | let env = TraitEnvironment::lower(db, resolver); | ||
180 | match mode { | 183 | match mode { |
181 | LookupMode::MethodCall => { | 184 | LookupMode::MethodCall => { |
182 | // For method calls, rust first does any number of autoderef, and then one | 185 | // For method calls, rust first does any number of autoderef, and then one |
@@ -209,7 +212,9 @@ pub fn iterate_method_candidates<T>( | |||
209 | if let Some(result) = iterate_method_candidates_with_autoref( | 212 | if let Some(result) = iterate_method_candidates_with_autoref( |
210 | &deref_chain[i..], | 213 | &deref_chain[i..], |
211 | db, | 214 | db, |
212 | resolver, | 215 | env.clone(), |
216 | krate, | ||
217 | &traits_in_scope, | ||
213 | name, | 218 | name, |
214 | &mut callback, | 219 | &mut callback, |
215 | ) { | 220 | ) { |
@@ -220,7 +225,15 @@ pub fn iterate_method_candidates<T>( | |||
220 | } | 225 | } |
221 | LookupMode::Path => { | 226 | LookupMode::Path => { |
222 | // No autoderef for path lookups | 227 | // No autoderef for path lookups |
223 | iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback) | 228 | iterate_method_candidates_for_self_ty( |
229 | &ty, | ||
230 | db, | ||
231 | env, | ||
232 | krate, | ||
233 | &traits_in_scope, | ||
234 | name, | ||
235 | &mut callback, | ||
236 | ) | ||
224 | } | 237 | } |
225 | } | 238 | } |
226 | } | 239 | } |
@@ -228,7 +241,9 @@ pub fn iterate_method_candidates<T>( | |||
228 | fn iterate_method_candidates_with_autoref<T>( | 241 | fn iterate_method_candidates_with_autoref<T>( |
229 | deref_chain: &[Canonical<Ty>], | 242 | deref_chain: &[Canonical<Ty>], |
230 | db: &impl HirDatabase, | 243 | db: &impl HirDatabase, |
231 | resolver: &Resolver, | 244 | env: Arc<TraitEnvironment>, |
245 | krate: CrateId, | ||
246 | traits_in_scope: &FxHashSet<TraitId>, | ||
232 | name: Option<&Name>, | 247 | name: Option<&Name>, |
233 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 248 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
234 | ) -> Option<T> { | 249 | ) -> Option<T> { |
@@ -236,7 +251,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
236 | &deref_chain[0], | 251 | &deref_chain[0], |
237 | &deref_chain[1..], | 252 | &deref_chain[1..], |
238 | db, | 253 | db, |
239 | resolver, | 254 | env.clone(), |
255 | krate, | ||
256 | &traits_in_scope, | ||
240 | name, | 257 | name, |
241 | &mut callback, | 258 | &mut callback, |
242 | ) { | 259 | ) { |
@@ -250,7 +267,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
250 | &refed, | 267 | &refed, |
251 | deref_chain, | 268 | deref_chain, |
252 | db, | 269 | db, |
253 | resolver, | 270 | env.clone(), |
271 | krate, | ||
272 | &traits_in_scope, | ||
254 | name, | 273 | name, |
255 | &mut callback, | 274 | &mut callback, |
256 | ) { | 275 | ) { |
@@ -264,7 +283,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
264 | &ref_muted, | 283 | &ref_muted, |
265 | deref_chain, | 284 | deref_chain, |
266 | db, | 285 | db, |
267 | resolver, | 286 | env.clone(), |
287 | krate, | ||
288 | &traits_in_scope, | ||
268 | name, | 289 | name, |
269 | &mut callback, | 290 | &mut callback, |
270 | ) { | 291 | ) { |
@@ -277,14 +298,15 @@ fn iterate_method_candidates_by_receiver<T>( | |||
277 | receiver_ty: &Canonical<Ty>, | 298 | receiver_ty: &Canonical<Ty>, |
278 | rest_of_deref_chain: &[Canonical<Ty>], | 299 | rest_of_deref_chain: &[Canonical<Ty>], |
279 | db: &impl HirDatabase, | 300 | db: &impl HirDatabase, |
280 | resolver: &Resolver, | 301 | env: Arc<TraitEnvironment>, |
302 | krate: CrateId, | ||
303 | traits_in_scope: &FxHashSet<TraitId>, | ||
281 | name: Option<&Name>, | 304 | name: Option<&Name>, |
282 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 305 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
283 | ) -> Option<T> { | 306 | ) -> Option<T> { |
284 | // We're looking for methods with *receiver* type receiver_ty. These could | 307 | // We're looking for methods with *receiver* type receiver_ty. These could |
285 | // be found in any of the derefs of receiver_ty, so we have to go through | 308 | // be found in any of the derefs of receiver_ty, so we have to go through |
286 | // that. | 309 | // that. |
287 | let krate = resolver.krate()?; | ||
288 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { | 310 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { |
289 | if let Some(result) = | 311 | if let Some(result) = |
290 | iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) | 312 | iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) |
@@ -296,7 +318,9 @@ fn iterate_method_candidates_by_receiver<T>( | |||
296 | if let Some(result) = iterate_trait_method_candidates( | 318 | if let Some(result) = iterate_trait_method_candidates( |
297 | self_ty, | 319 | self_ty, |
298 | db, | 320 | db, |
299 | resolver, | 321 | env.clone(), |
322 | krate, | ||
323 | &traits_in_scope, | ||
300 | name, | 324 | name, |
301 | Some(receiver_ty), | 325 | Some(receiver_ty), |
302 | &mut callback, | 326 | &mut callback, |
@@ -310,17 +334,25 @@ fn iterate_method_candidates_by_receiver<T>( | |||
310 | fn iterate_method_candidates_for_self_ty<T>( | 334 | fn iterate_method_candidates_for_self_ty<T>( |
311 | self_ty: &Canonical<Ty>, | 335 | self_ty: &Canonical<Ty>, |
312 | db: &impl HirDatabase, | 336 | db: &impl HirDatabase, |
313 | resolver: &Resolver, | 337 | env: Arc<TraitEnvironment>, |
338 | krate: CrateId, | ||
339 | traits_in_scope: &FxHashSet<TraitId>, | ||
314 | name: Option<&Name>, | 340 | name: Option<&Name>, |
315 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 341 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
316 | ) -> Option<T> { | 342 | ) -> Option<T> { |
317 | let krate = resolver.krate()?; | ||
318 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { | 343 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { |
319 | return Some(result); | 344 | return Some(result); |
320 | } | 345 | } |
321 | if let Some(result) = | 346 | if let Some(result) = iterate_trait_method_candidates( |
322 | iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback) | 347 | self_ty, |
323 | { | 348 | db, |
349 | env, | ||
350 | krate, | ||
351 | traits_in_scope, | ||
352 | name, | ||
353 | None, | ||
354 | &mut callback, | ||
355 | ) { | ||
324 | return Some(result); | 356 | return Some(result); |
325 | } | 357 | } |
326 | None | 358 | None |
@@ -329,14 +361,13 @@ fn iterate_method_candidates_for_self_ty<T>( | |||
329 | fn iterate_trait_method_candidates<T>( | 361 | fn iterate_trait_method_candidates<T>( |
330 | self_ty: &Canonical<Ty>, | 362 | self_ty: &Canonical<Ty>, |
331 | db: &impl HirDatabase, | 363 | db: &impl HirDatabase, |
332 | resolver: &Resolver, | 364 | env: Arc<TraitEnvironment>, |
365 | krate: CrateId, | ||
366 | traits_in_scope: &FxHashSet<TraitId>, | ||
333 | name: Option<&Name>, | 367 | name: Option<&Name>, |
334 | receiver_ty: Option<&Canonical<Ty>>, | 368 | receiver_ty: Option<&Canonical<Ty>>, |
335 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 369 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
336 | ) -> Option<T> { | 370 | ) -> Option<T> { |
337 | let krate = resolver.krate()?; | ||
338 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | ||
339 | let env = TraitEnvironment::lower(db, resolver); | ||
340 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 371 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
341 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); | 372 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); |
342 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 373 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
@@ -344,8 +375,7 @@ fn iterate_trait_method_candidates<T>( | |||
344 | .trait_predicates_for_self_ty(&self_ty.value) | 375 | .trait_predicates_for_self_ty(&self_ty.value) |
345 | .map(|tr| tr.trait_) | 376 | .map(|tr| tr.trait_) |
346 | .flat_map(|t| all_super_traits(db, t)); | 377 | .flat_map(|t| all_super_traits(db, t)); |
347 | let traits = | 378 | let traits = inherent_trait.chain(traits_from_env).chain(traits_in_scope.iter().copied()); |
348 | inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter()); | ||
349 | 'traits: for t in traits { | 379 | 'traits: for t in traits { |
350 | let data = db.trait_data(t); | 380 | let data = db.trait_data(t); |
351 | 381 | ||