aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs129
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
291pub 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
330fn iterate_method_candidates_with_autoref<T>( 357fn 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
386fn iterate_method_candidates_by_receiver<T>( 413fn 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
423fn iterate_method_candidates_for_self_ty<T>( 448fn 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
450fn iterate_trait_method_candidates<T>( 463fn 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
500fn iterate_inherent_methods<T>( 513fn 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.