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