diff options
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 129 |
1 files changed, 73 insertions, 56 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index ed638c195..8b59a8bd6 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -271,6 +271,33 @@ pub fn iterate_method_candidates<T>( | |||
271 | mode: LookupMode, | 271 | mode: LookupMode, |
272 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 272 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
273 | ) -> Option<T> { | 273 | ) -> Option<T> { |
274 | let mut slot = None; | ||
275 | iterate_method_candidates_impl( | ||
276 | ty, | ||
277 | db, | ||
278 | env, | ||
279 | krate, | ||
280 | traits_in_scope, | ||
281 | name, | ||
282 | mode, | ||
283 | &mut |ty, item| { | ||
284 | slot = callback(ty, item); | ||
285 | slot.is_some() | ||
286 | }, | ||
287 | ); | ||
288 | slot | ||
289 | } | ||
290 | |||
291 | pub fn iterate_method_candidates_impl( | ||
292 | ty: &Canonical<Ty>, | ||
293 | db: &dyn HirDatabase, | ||
294 | env: Arc<TraitEnvironment>, | ||
295 | krate: CrateId, | ||
296 | traits_in_scope: &FxHashSet<TraitId>, | ||
297 | name: Option<&Name>, | ||
298 | mode: LookupMode, | ||
299 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | ||
300 | ) -> bool { | ||
274 | match mode { | 301 | match mode { |
275 | LookupMode::MethodCall => { | 302 | LookupMode::MethodCall => { |
276 | // For method calls, rust first does any number of autoderef, and then one | 303 | // For method calls, rust first does any number of autoderef, and then one |
@@ -298,19 +325,19 @@ pub fn iterate_method_candidates<T>( | |||
298 | 325 | ||
299 | let deref_chain = autoderef_method_receiver(db, krate, ty); | 326 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
300 | for i in 0..deref_chain.len() { | 327 | for i in 0..deref_chain.len() { |
301 | if let Some(result) = iterate_method_candidates_with_autoref( | 328 | if iterate_method_candidates_with_autoref( |
302 | &deref_chain[i..], | 329 | &deref_chain[i..], |
303 | db, | 330 | db, |
304 | env.clone(), | 331 | env.clone(), |
305 | krate, | 332 | krate, |
306 | traits_in_scope, | 333 | traits_in_scope, |
307 | name, | 334 | name, |
308 | &mut callback, | 335 | callback, |
309 | ) { | 336 | ) { |
310 | return Some(result); | 337 | return true; |
311 | } | 338 | } |
312 | } | 339 | } |
313 | None | 340 | false |
314 | } | 341 | } |
315 | LookupMode::Path => { | 342 | LookupMode::Path => { |
316 | // No autoderef for path lookups | 343 | // No autoderef for path lookups |
@@ -321,22 +348,22 @@ pub fn iterate_method_candidates<T>( | |||
321 | krate, | 348 | krate, |
322 | traits_in_scope, | 349 | traits_in_scope, |
323 | name, | 350 | name, |
324 | &mut callback, | 351 | callback, |
325 | ) | 352 | ) |
326 | } | 353 | } |
327 | } | 354 | } |
328 | } | 355 | } |
329 | 356 | ||
330 | fn iterate_method_candidates_with_autoref<T>( | 357 | fn iterate_method_candidates_with_autoref( |
331 | deref_chain: &[Canonical<Ty>], | 358 | deref_chain: &[Canonical<Ty>], |
332 | db: &dyn HirDatabase, | 359 | db: &dyn HirDatabase, |
333 | env: Arc<TraitEnvironment>, | 360 | env: Arc<TraitEnvironment>, |
334 | krate: CrateId, | 361 | krate: CrateId, |
335 | traits_in_scope: &FxHashSet<TraitId>, | 362 | traits_in_scope: &FxHashSet<TraitId>, |
336 | name: Option<&Name>, | 363 | name: Option<&Name>, |
337 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 364 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
338 | ) -> Option<T> { | 365 | ) -> bool { |
339 | if let Some(result) = iterate_method_candidates_by_receiver( | 366 | if iterate_method_candidates_by_receiver( |
340 | &deref_chain[0], | 367 | &deref_chain[0], |
341 | &deref_chain[1..], | 368 | &deref_chain[1..], |
342 | db, | 369 | db, |
@@ -346,13 +373,13 @@ fn iterate_method_candidates_with_autoref<T>( | |||
346 | name, | 373 | name, |
347 | &mut callback, | 374 | &mut callback, |
348 | ) { | 375 | ) { |
349 | return Some(result); | 376 | return true; |
350 | } | 377 | } |
351 | let refed = Canonical { | 378 | let refed = Canonical { |
352 | num_vars: deref_chain[0].num_vars, | 379 | num_vars: deref_chain[0].num_vars, |
353 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), | 380 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), |
354 | }; | 381 | }; |
355 | if let Some(result) = iterate_method_candidates_by_receiver( | 382 | if iterate_method_candidates_by_receiver( |
356 | &refed, | 383 | &refed, |
357 | deref_chain, | 384 | deref_chain, |
358 | db, | 385 | db, |
@@ -362,13 +389,13 @@ fn iterate_method_candidates_with_autoref<T>( | |||
362 | name, | 389 | name, |
363 | &mut callback, | 390 | &mut callback, |
364 | ) { | 391 | ) { |
365 | return Some(result); | 392 | return true; |
366 | } | 393 | } |
367 | let ref_muted = Canonical { | 394 | let ref_muted = Canonical { |
368 | num_vars: deref_chain[0].num_vars, | 395 | num_vars: deref_chain[0].num_vars, |
369 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), | 396 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), |
370 | }; | 397 | }; |
371 | if let Some(result) = iterate_method_candidates_by_receiver( | 398 | if iterate_method_candidates_by_receiver( |
372 | &ref_muted, | 399 | &ref_muted, |
373 | deref_chain, | 400 | deref_chain, |
374 | db, | 401 | db, |
@@ -378,12 +405,12 @@ fn iterate_method_candidates_with_autoref<T>( | |||
378 | name, | 405 | name, |
379 | &mut callback, | 406 | &mut callback, |
380 | ) { | 407 | ) { |
381 | return Some(result); | 408 | return true; |
382 | } | 409 | } |
383 | None | 410 | false |
384 | } | 411 | } |
385 | 412 | ||
386 | fn iterate_method_candidates_by_receiver<T>( | 413 | fn iterate_method_candidates_by_receiver( |
387 | receiver_ty: &Canonical<Ty>, | 414 | receiver_ty: &Canonical<Ty>, |
388 | rest_of_deref_chain: &[Canonical<Ty>], | 415 | rest_of_deref_chain: &[Canonical<Ty>], |
389 | db: &dyn HirDatabase, | 416 | db: &dyn HirDatabase, |
@@ -391,20 +418,18 @@ fn iterate_method_candidates_by_receiver<T>( | |||
391 | krate: CrateId, | 418 | krate: CrateId, |
392 | traits_in_scope: &FxHashSet<TraitId>, | 419 | traits_in_scope: &FxHashSet<TraitId>, |
393 | name: Option<&Name>, | 420 | name: Option<&Name>, |
394 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 421 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
395 | ) -> Option<T> { | 422 | ) -> bool { |
396 | // We're looking for methods with *receiver* type receiver_ty. These could | 423 | // We're looking for methods with *receiver* type receiver_ty. These could |
397 | // be found in any of the derefs of receiver_ty, so we have to go through | 424 | // be found in any of the derefs of receiver_ty, so we have to go through |
398 | // that. | 425 | // that. |
399 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { | 426 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { |
400 | if let Some(result) = | 427 | if iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) { |
401 | iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) | 428 | return true; |
402 | { | ||
403 | return Some(result); | ||
404 | } | 429 | } |
405 | } | 430 | } |
406 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { | 431 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { |
407 | if let Some(result) = iterate_trait_method_candidates( | 432 | if iterate_trait_method_candidates( |
408 | self_ty, | 433 | self_ty, |
409 | db, | 434 | db, |
410 | env.clone(), | 435 | env.clone(), |
@@ -414,40 +439,28 @@ fn iterate_method_candidates_by_receiver<T>( | |||
414 | Some(receiver_ty), | 439 | Some(receiver_ty), |
415 | &mut callback, | 440 | &mut callback, |
416 | ) { | 441 | ) { |
417 | return Some(result); | 442 | return true; |
418 | } | 443 | } |
419 | } | 444 | } |
420 | None | 445 | false |
421 | } | 446 | } |
422 | 447 | ||
423 | fn iterate_method_candidates_for_self_ty<T>( | 448 | fn iterate_method_candidates_for_self_ty( |
424 | self_ty: &Canonical<Ty>, | 449 | self_ty: &Canonical<Ty>, |
425 | db: &dyn HirDatabase, | 450 | db: &dyn HirDatabase, |
426 | env: Arc<TraitEnvironment>, | 451 | env: Arc<TraitEnvironment>, |
427 | krate: CrateId, | 452 | krate: CrateId, |
428 | traits_in_scope: &FxHashSet<TraitId>, | 453 | traits_in_scope: &FxHashSet<TraitId>, |
429 | name: Option<&Name>, | 454 | name: Option<&Name>, |
430 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 455 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
431 | ) -> Option<T> { | 456 | ) -> bool { |
432 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { | 457 | if iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { |
433 | return Some(result); | 458 | return true; |
434 | } | ||
435 | if let Some(result) = iterate_trait_method_candidates( | ||
436 | self_ty, | ||
437 | db, | ||
438 | env, | ||
439 | krate, | ||
440 | traits_in_scope, | ||
441 | name, | ||
442 | None, | ||
443 | &mut callback, | ||
444 | ) { | ||
445 | return Some(result); | ||
446 | } | 459 | } |
447 | None | 460 | iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) |
448 | } | 461 | } |
449 | 462 | ||
450 | fn iterate_trait_method_candidates<T>( | 463 | fn iterate_trait_method_candidates( |
451 | self_ty: &Canonical<Ty>, | 464 | self_ty: &Canonical<Ty>, |
452 | db: &dyn HirDatabase, | 465 | db: &dyn HirDatabase, |
453 | env: Arc<TraitEnvironment>, | 466 | env: Arc<TraitEnvironment>, |
@@ -455,8 +468,8 @@ fn iterate_trait_method_candidates<T>( | |||
455 | traits_in_scope: &FxHashSet<TraitId>, | 468 | traits_in_scope: &FxHashSet<TraitId>, |
456 | name: Option<&Name>, | 469 | name: Option<&Name>, |
457 | receiver_ty: Option<&Canonical<Ty>>, | 470 | receiver_ty: Option<&Canonical<Ty>>, |
458 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 471 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
459 | ) -> Option<T> { | 472 | ) -> bool { |
460 | // if ty is `dyn Trait`, the trait doesn't need to be in scope | 473 | // if ty is `dyn Trait`, the trait doesn't need to be in scope |
461 | let inherent_trait = | 474 | let inherent_trait = |
462 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | 475 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); |
@@ -489,23 +502,27 @@ fn iterate_trait_method_candidates<T>( | |||
489 | } | 502 | } |
490 | } | 503 | } |
491 | known_implemented = true; | 504 | known_implemented = true; |
492 | if let Some(result) = callback(&self_ty.value, *item) { | 505 | if callback(&self_ty.value, *item) { |
493 | return Some(result); | 506 | return true; |
494 | } | 507 | } |
495 | } | 508 | } |
496 | } | 509 | } |
497 | None | 510 | false |
498 | } | 511 | } |
499 | 512 | ||
500 | fn iterate_inherent_methods<T>( | 513 | fn iterate_inherent_methods( |
501 | self_ty: &Canonical<Ty>, | 514 | self_ty: &Canonical<Ty>, |
502 | db: &dyn HirDatabase, | 515 | db: &dyn HirDatabase, |
503 | name: Option<&Name>, | 516 | name: Option<&Name>, |
504 | receiver_ty: Option<&Canonical<Ty>>, | 517 | receiver_ty: Option<&Canonical<Ty>>, |
505 | krate: CrateId, | 518 | krate: CrateId, |
506 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 519 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
507 | ) -> Option<T> { | 520 | ) -> bool { |
508 | for krate in self_ty.value.def_crates(db, krate)? { | 521 | let def_crates = match self_ty.value.def_crates(db, krate) { |
522 | Some(k) => k, | ||
523 | None => return false, | ||
524 | }; | ||
525 | for krate in def_crates { | ||
509 | let impls = db.impls_in_crate(krate); | 526 | let impls = db.impls_in_crate(krate); |
510 | 527 | ||
511 | for impl_def in impls.lookup_impl_defs(&self_ty.value) { | 528 | for impl_def in impls.lookup_impl_defs(&self_ty.value) { |
@@ -521,13 +538,13 @@ fn iterate_inherent_methods<T>( | |||
521 | test_utils::mark::hit!(impl_self_type_match_without_receiver); | 538 | test_utils::mark::hit!(impl_self_type_match_without_receiver); |
522 | continue; | 539 | continue; |
523 | } | 540 | } |
524 | if let Some(result) = callback(&self_ty.value, item) { | 541 | if callback(&self_ty.value, item) { |
525 | return Some(result); | 542 | return true; |
526 | } | 543 | } |
527 | } | 544 | } |
528 | } | 545 | } |
529 | } | 546 | } |
530 | None | 547 | false |
531 | } | 548 | } |
532 | 549 | ||
533 | /// Returns the self type for the index trait call. | 550 | /// Returns the self type for the index trait call. |