aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs198
1 files changed, 134 insertions, 64 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index e83b39456..8b59a8bd6 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -38,18 +38,53 @@ impl TyFingerprint {
38 } 38 }
39} 39}
40 40
41/// A queryable and mergeable collection of impls.
41#[derive(Debug, PartialEq, Eq)] 42#[derive(Debug, PartialEq, Eq)]
42pub struct CrateImplDefs { 43pub struct CrateImplDefs {
43 impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 44 inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
44 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, 45 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
45} 46}
46 47
47impl CrateImplDefs { 48impl CrateImplDefs {
48 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { 49 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
49 let _p = profile("impls_in_crate_query"); 50 let _p = profile("impls_in_crate_query");
50 let mut res = 51 let mut res = CrateImplDefs {
51 CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; 52 inherent_impls: FxHashMap::default(),
53 impls_by_trait: FxHashMap::default(),
54 };
55 res.fill(db, krate);
56
57 Arc::new(res)
58 }
59
60 /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61 ///
62 /// The full set of impls that can be used by `krate` is the returned map plus all the impls
63 /// from `krate` itself.
64 pub(crate) fn impls_from_deps_query(
65 db: &dyn HirDatabase,
66 krate: CrateId,
67 ) -> Arc<CrateImplDefs> {
68 let _p = profile("impls_from_deps_query");
69 let crate_graph = db.crate_graph();
70 let mut res = CrateImplDefs {
71 inherent_impls: FxHashMap::default(),
72 impls_by_trait: FxHashMap::default(),
73 };
74
75 // For each dependency, calculate `impls_from_deps` recursively, then add its own
76 // `impls_in_crate`.
77 // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid
78 // wasting memory.
79 for dep in &crate_graph[krate].dependencies {
80 res.merge(&db.impls_from_deps(dep.crate_id));
81 res.merge(&db.impls_in_crate(dep.crate_id));
82 }
52 83
84 Arc::new(res)
85 }
86
87 fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
53 let crate_def_map = db.crate_def_map(krate); 88 let crate_def_map = db.crate_def_map(krate);
54 for (_module_id, module_data) in crate_def_map.modules.iter() { 89 for (_module_id, module_data) in crate_def_map.modules.iter() {
55 for impl_id in module_data.scope.impls() { 90 for impl_id in module_data.scope.impls() {
@@ -57,7 +92,7 @@ impl CrateImplDefs {
57 Some(tr) => { 92 Some(tr) => {
58 let self_ty = db.impl_self_ty(impl_id); 93 let self_ty = db.impl_self_ty(impl_id);
59 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); 94 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
60 res.impls_by_trait 95 self.impls_by_trait
61 .entry(tr.value.trait_) 96 .entry(tr.value.trait_)
62 .or_default() 97 .or_default()
63 .entry(self_ty_fp) 98 .entry(self_ty_fp)
@@ -67,18 +102,36 @@ impl CrateImplDefs {
67 None => { 102 None => {
68 let self_ty = db.impl_self_ty(impl_id); 103 let self_ty = db.impl_self_ty(impl_id);
69 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { 104 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
70 res.impls.entry(self_ty_fp).or_default().push(impl_id); 105 self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
71 } 106 }
72 } 107 }
73 } 108 }
74 } 109 }
75 } 110 }
111 }
112
113 fn merge(&mut self, other: &Self) {
114 for (fp, impls) in &other.inherent_impls {
115 let vec = self.inherent_impls.entry(*fp).or_default();
116 vec.extend(impls);
117 vec.sort();
118 vec.dedup();
119 }
76 120
77 Arc::new(res) 121 for (trait_, other_map) in &other.impls_by_trait {
122 let map = self.impls_by_trait.entry(*trait_).or_default();
123 for (fp, impls) in other_map {
124 let vec = map.entry(*fp).or_default();
125 vec.extend(impls);
126 vec.sort();
127 vec.dedup();
128 }
129 }
78 } 130 }
131
79 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 132 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
80 let fingerprint = TyFingerprint::for_impl(ty); 133 let fingerprint = TyFingerprint::for_impl(ty);
81 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 134 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
82 } 135 }
83 136
84 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { 137 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -110,7 +163,7 @@ impl CrateImplDefs {
110 } 163 }
111 164
112 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 165 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
113 self.impls 166 self.inherent_impls
114 .values() 167 .values()
115 .chain(self.impls_by_trait.values().flat_map(|m| m.values())) 168 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
116 .flatten() 169 .flatten()
@@ -218,6 +271,33 @@ pub fn iterate_method_candidates<T>(
218 mode: LookupMode, 271 mode: LookupMode,
219 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 272 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
220) -> 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 {
221 match mode { 301 match mode {
222 LookupMode::MethodCall => { 302 LookupMode::MethodCall => {
223 // 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
@@ -245,19 +325,19 @@ pub fn iterate_method_candidates<T>(
245 325
246 let deref_chain = autoderef_method_receiver(db, krate, ty); 326 let deref_chain = autoderef_method_receiver(db, krate, ty);
247 for i in 0..deref_chain.len() { 327 for i in 0..deref_chain.len() {
248 if let Some(result) = iterate_method_candidates_with_autoref( 328 if iterate_method_candidates_with_autoref(
249 &deref_chain[i..], 329 &deref_chain[i..],
250 db, 330 db,
251 env.clone(), 331 env.clone(),
252 krate, 332 krate,
253 traits_in_scope, 333 traits_in_scope,
254 name, 334 name,
255 &mut callback, 335 callback,
256 ) { 336 ) {
257 return Some(result); 337 return true;
258 } 338 }
259 } 339 }
260 None 340 false
261 } 341 }
262 LookupMode::Path => { 342 LookupMode::Path => {
263 // No autoderef for path lookups 343 // No autoderef for path lookups
@@ -268,22 +348,22 @@ pub fn iterate_method_candidates<T>(
268 krate, 348 krate,
269 traits_in_scope, 349 traits_in_scope,
270 name, 350 name,
271 &mut callback, 351 callback,
272 ) 352 )
273 } 353 }
274 } 354 }
275} 355}
276 356
277fn iterate_method_candidates_with_autoref<T>( 357fn iterate_method_candidates_with_autoref(
278 deref_chain: &[Canonical<Ty>], 358 deref_chain: &[Canonical<Ty>],
279 db: &dyn HirDatabase, 359 db: &dyn HirDatabase,
280 env: Arc<TraitEnvironment>, 360 env: Arc<TraitEnvironment>,
281 krate: CrateId, 361 krate: CrateId,
282 traits_in_scope: &FxHashSet<TraitId>, 362 traits_in_scope: &FxHashSet<TraitId>,
283 name: Option<&Name>, 363 name: Option<&Name>,
284 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 364 mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
285) -> Option<T> { 365) -> bool {
286 if let Some(result) = iterate_method_candidates_by_receiver( 366 if iterate_method_candidates_by_receiver(
287 &deref_chain[0], 367 &deref_chain[0],
288 &deref_chain[1..], 368 &deref_chain[1..],
289 db, 369 db,
@@ -293,13 +373,13 @@ fn iterate_method_candidates_with_autoref<T>(
293 name, 373 name,
294 &mut callback, 374 &mut callback,
295 ) { 375 ) {
296 return Some(result); 376 return true;
297 } 377 }
298 let refed = Canonical { 378 let refed = Canonical {
299 num_vars: deref_chain[0].num_vars, 379 num_vars: deref_chain[0].num_vars,
300 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()),
301 }; 381 };
302 if let Some(result) = iterate_method_candidates_by_receiver( 382 if iterate_method_candidates_by_receiver(
303 &refed, 383 &refed,
304 deref_chain, 384 deref_chain,
305 db, 385 db,
@@ -309,13 +389,13 @@ fn iterate_method_candidates_with_autoref<T>(
309 name, 389 name,
310 &mut callback, 390 &mut callback,
311 ) { 391 ) {
312 return Some(result); 392 return true;
313 } 393 }
314 let ref_muted = Canonical { 394 let ref_muted = Canonical {
315 num_vars: deref_chain[0].num_vars, 395 num_vars: deref_chain[0].num_vars,
316 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()),
317 }; 397 };
318 if let Some(result) = iterate_method_candidates_by_receiver( 398 if iterate_method_candidates_by_receiver(
319 &ref_muted, 399 &ref_muted,
320 deref_chain, 400 deref_chain,
321 db, 401 db,
@@ -325,12 +405,12 @@ fn iterate_method_candidates_with_autoref<T>(
325 name, 405 name,
326 &mut callback, 406 &mut callback,
327 ) { 407 ) {
328 return Some(result); 408 return true;
329 } 409 }
330 None 410 false
331} 411}
332 412
333fn iterate_method_candidates_by_receiver<T>( 413fn iterate_method_candidates_by_receiver(
334 receiver_ty: &Canonical<Ty>, 414 receiver_ty: &Canonical<Ty>,
335 rest_of_deref_chain: &[Canonical<Ty>], 415 rest_of_deref_chain: &[Canonical<Ty>],
336 db: &dyn HirDatabase, 416 db: &dyn HirDatabase,
@@ -338,20 +418,18 @@ fn iterate_method_candidates_by_receiver<T>(
338 krate: CrateId, 418 krate: CrateId,
339 traits_in_scope: &FxHashSet<TraitId>, 419 traits_in_scope: &FxHashSet<TraitId>,
340 name: Option<&Name>, 420 name: Option<&Name>,
341 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 421 mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
342) -> Option<T> { 422) -> bool {
343 // 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
344 // 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
345 // that. 425 // that.
346 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) {
347 if let Some(result) = 427 if iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) {
348 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) 428 return true;
349 {
350 return Some(result);
351 } 429 }
352 } 430 }
353 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) {
354 if let Some(result) = iterate_trait_method_candidates( 432 if iterate_trait_method_candidates(
355 self_ty, 433 self_ty,
356 db, 434 db,
357 env.clone(), 435 env.clone(),
@@ -361,40 +439,28 @@ fn iterate_method_candidates_by_receiver<T>(
361 Some(receiver_ty), 439 Some(receiver_ty),
362 &mut callback, 440 &mut callback,
363 ) { 441 ) {
364 return Some(result); 442 return true;
365 } 443 }
366 } 444 }
367 None 445 false
368} 446}
369 447
370fn iterate_method_candidates_for_self_ty<T>( 448fn iterate_method_candidates_for_self_ty(
371 self_ty: &Canonical<Ty>, 449 self_ty: &Canonical<Ty>,
372 db: &dyn HirDatabase, 450 db: &dyn HirDatabase,
373 env: Arc<TraitEnvironment>, 451 env: Arc<TraitEnvironment>,
374 krate: CrateId, 452 krate: CrateId,
375 traits_in_scope: &FxHashSet<TraitId>, 453 traits_in_scope: &FxHashSet<TraitId>,
376 name: Option<&Name>, 454 name: Option<&Name>,
377 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 455 mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
378) -> Option<T> { 456) -> bool {
379 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) {
380 return Some(result); 458 return true;
381 }
382 if let Some(result) = iterate_trait_method_candidates(
383 self_ty,
384 db,
385 env,
386 krate,
387 traits_in_scope,
388 name,
389 None,
390 &mut callback,
391 ) {
392 return Some(result);
393 } 459 }
394 None 460 iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback)
395} 461}
396 462
397fn iterate_trait_method_candidates<T>( 463fn iterate_trait_method_candidates(
398 self_ty: &Canonical<Ty>, 464 self_ty: &Canonical<Ty>,
399 db: &dyn HirDatabase, 465 db: &dyn HirDatabase,
400 env: Arc<TraitEnvironment>, 466 env: Arc<TraitEnvironment>,
@@ -402,8 +468,8 @@ fn iterate_trait_method_candidates<T>(
402 traits_in_scope: &FxHashSet<TraitId>, 468 traits_in_scope: &FxHashSet<TraitId>,
403 name: Option<&Name>, 469 name: Option<&Name>,
404 receiver_ty: Option<&Canonical<Ty>>, 470 receiver_ty: Option<&Canonical<Ty>>,
405 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 471 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
406) -> Option<T> { 472) -> bool {
407 // 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
408 let inherent_trait = 474 let inherent_trait =
409 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));
@@ -436,23 +502,27 @@ fn iterate_trait_method_candidates<T>(
436 } 502 }
437 } 503 }
438 known_implemented = true; 504 known_implemented = true;
439 if let Some(result) = callback(&self_ty.value, *item) { 505 if callback(&self_ty.value, *item) {
440 return Some(result); 506 return true;
441 } 507 }
442 } 508 }
443 } 509 }
444 None 510 false
445} 511}
446 512
447fn iterate_inherent_methods<T>( 513fn iterate_inherent_methods(
448 self_ty: &Canonical<Ty>, 514 self_ty: &Canonical<Ty>,
449 db: &dyn HirDatabase, 515 db: &dyn HirDatabase,
450 name: Option<&Name>, 516 name: Option<&Name>,
451 receiver_ty: Option<&Canonical<Ty>>, 517 receiver_ty: Option<&Canonical<Ty>>,
452 krate: CrateId, 518 krate: CrateId,
453 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 519 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
454) -> Option<T> { 520) -> bool {
455 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 {
456 let impls = db.impls_in_crate(krate); 526 let impls = db.impls_in_crate(krate);
457 527
458 for impl_def in impls.lookup_impl_defs(&self_ty.value) { 528 for impl_def in impls.lookup_impl_defs(&self_ty.value) {
@@ -468,13 +538,13 @@ fn iterate_inherent_methods<T>(
468 test_utils::mark::hit!(impl_self_type_match_without_receiver); 538 test_utils::mark::hit!(impl_self_type_match_without_receiver);
469 continue; 539 continue;
470 } 540 }
471 if let Some(result) = callback(&self_ty.value, item) { 541 if callback(&self_ty.value, item) {
472 return Some(result); 542 return true;
473 } 543 }
474 } 544 }
475 } 545 }
476 } 546 }
477 None 547 false
478} 548}
479 549
480/// Returns the self type for the index trait call. 550/// Returns the self type for the index trait call.