aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-07-31 03:12:44 +0100
committerZac Pullar-Strecker <[email protected]>2020-07-31 03:12:44 +0100
commitf05d7b41a719d848844b054a16477b29d0f063c6 (patch)
tree0a8a0946e8aef2ce64d4c13d0035ba41cce2daf3 /crates/ra_hir_ty/src/method_resolution.rs
parent73ff610e41959e3e7c78a2b4b25b086883132956 (diff)
parent6b7cb8b5ab539fc4333ce34bc29bf77c976f232a (diff)
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Hasn't fixed tests yet.
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs302
1 files changed, 180 insertions, 122 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index c19519cf1..fb4b30a13 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -2,12 +2,14 @@
2//! For details about how this works in rustc, see the method lookup page in the 2//! For details about how this works in rustc, see the method lookup page in the
3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html) 3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. 4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
5use std::sync::Arc; 5use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, 9 builtin_type::{IntBitness, Signedness},
10 HasModule, ImplId, Lookup, TraitId, 10 lang_item::LangItemTarget,
11 type_ref::Mutability,
12 AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
11}; 13};
12use hir_expand::name::Name; 14use hir_expand::name::Name;
13use ra_db::CrateId; 15use ra_db::CrateId;
@@ -16,8 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
16 18
17use super::Substs; 19use super::Substs;
18use crate::{ 20use crate::{
19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, 21 autoderef,
20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 22 db::HirDatabase,
23 primitive::{FloatBitness, FloatTy, IntTy},
24 utils::all_super_traits,
25 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
26 TypeCtor, TypeWalk,
21}; 27};
22 28
23/// This is used as a key for indexing impls. 29/// This is used as a key for indexing impls.
@@ -38,136 +44,187 @@ impl TyFingerprint {
38 } 44 }
39} 45}
40 46
41/// A queryable and mergeable collection of impls. 47pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
42#[derive(Debug, PartialEq, Eq)] 48 TyFingerprint::Apply(TypeCtor::Int(IntTy {
43pub struct CrateImplDefs { 49 signedness: Signedness::Unsigned,
44 inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 50 bitness: IntBitness::X8,
45 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, 51 })),
52 TyFingerprint::Apply(TypeCtor::Int(IntTy {
53 signedness: Signedness::Unsigned,
54 bitness: IntBitness::X16,
55 })),
56 TyFingerprint::Apply(TypeCtor::Int(IntTy {
57 signedness: Signedness::Unsigned,
58 bitness: IntBitness::X32,
59 })),
60 TyFingerprint::Apply(TypeCtor::Int(IntTy {
61 signedness: Signedness::Unsigned,
62 bitness: IntBitness::X64,
63 })),
64 TyFingerprint::Apply(TypeCtor::Int(IntTy {
65 signedness: Signedness::Unsigned,
66 bitness: IntBitness::X128,
67 })),
68 TyFingerprint::Apply(TypeCtor::Int(IntTy {
69 signedness: Signedness::Unsigned,
70 bitness: IntBitness::Xsize,
71 })),
72 TyFingerprint::Apply(TypeCtor::Int(IntTy {
73 signedness: Signedness::Signed,
74 bitness: IntBitness::X8,
75 })),
76 TyFingerprint::Apply(TypeCtor::Int(IntTy {
77 signedness: Signedness::Signed,
78 bitness: IntBitness::X16,
79 })),
80 TyFingerprint::Apply(TypeCtor::Int(IntTy {
81 signedness: Signedness::Signed,
82 bitness: IntBitness::X32,
83 })),
84 TyFingerprint::Apply(TypeCtor::Int(IntTy {
85 signedness: Signedness::Signed,
86 bitness: IntBitness::X64,
87 })),
88 TyFingerprint::Apply(TypeCtor::Int(IntTy {
89 signedness: Signedness::Signed,
90 bitness: IntBitness::X128,
91 })),
92 TyFingerprint::Apply(TypeCtor::Int(IntTy {
93 signedness: Signedness::Signed,
94 bitness: IntBitness::Xsize,
95 })),
96];
97
98pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
99 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })),
100 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })),
101];
102
103/// Trait impls defined or available in some crate.
104#[derive(Debug, Eq, PartialEq)]
105pub struct TraitImpls {
106 // If the `Option<TyFingerprint>` is `None`, the impl may apply to any self type.
107 map: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
46} 108}
47 109
48impl CrateImplDefs { 110impl TraitImpls {
49 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { 111 pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
50 let _p = profile("impls_in_crate_query"); 112 let _p = profile("trait_impls_in_crate_query");
51 let mut res = CrateImplDefs { 113 let mut impls = Self { map: FxHashMap::default() };
52 inherent_impls: FxHashMap::default(),
53 impls_by_trait: FxHashMap::default(),
54 };
55 res.fill(db, krate);
56 114
57 Arc::new(res) 115 let crate_def_map = db.crate_def_map(krate);
116 for (_module_id, module_data) in crate_def_map.modules.iter() {
117 for impl_id in module_data.scope.impls() {
118 let target_trait = match db.impl_trait(impl_id) {
119 Some(tr) => tr.value.trait_,
120 None => continue,
121 };
122 let self_ty = db.impl_self_ty(impl_id);
123 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
124 impls
125 .map
126 .entry(target_trait)
127 .or_default()
128 .entry(self_ty_fp)
129 .or_default()
130 .push(impl_id);
131 }
132 }
133
134 Arc::new(impls)
58 } 135 }
59 136
60 /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`. 137 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
61 /// 138 let _p = profile("trait_impls_in_deps_query");
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(); 139 let crate_graph = db.crate_graph();
70 let mut res = CrateImplDefs { 140 let mut res = Self { map: FxHashMap::default() };
71 inherent_impls: FxHashMap::default(),
72 impls_by_trait: FxHashMap::default(),
73 };
74 141
75 // For each dependency, calculate `impls_from_deps` recursively, then add its own 142 for krate in crate_graph.transitive_deps(krate) {
76 // `impls_in_crate`. 143 res.merge(&db.trait_impls_in_crate(krate));
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 } 144 }
83 145
84 Arc::new(res) 146 Arc::new(res)
85 } 147 }
86 148
87 fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
88 let crate_def_map = db.crate_def_map(krate);
89 for (_module_id, module_data) in crate_def_map.modules.iter() {
90 for impl_id in module_data.scope.impls() {
91 match db.impl_trait(impl_id) {
92 Some(tr) => {
93 let self_ty = db.impl_self_ty(impl_id);
94 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
95 self.impls_by_trait
96 .entry(tr.value.trait_)
97 .or_default()
98 .entry(self_ty_fp)
99 .or_default()
100 .push(impl_id);
101 }
102 None => {
103 let self_ty = db.impl_self_ty(impl_id);
104 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
105 self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
106 }
107 }
108 }
109 }
110 }
111 }
112
113 fn merge(&mut self, other: &Self) { 149 fn merge(&mut self, other: &Self) {
114 for (fp, impls) in &other.inherent_impls { 150 for (trait_, other_map) in &other.map {
115 let vec = self.inherent_impls.entry(*fp).or_default(); 151 let map = self.map.entry(*trait_).or_default();
116 vec.extend(impls);
117 vec.sort();
118 vec.dedup();
119 }
120
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 { 152 for (fp, impls) in other_map {
124 let vec = map.entry(*fp).or_default(); 153 let vec = map.entry(*fp).or_default();
125 vec.extend(impls); 154 vec.extend(impls);
126 vec.sort();
127 vec.dedup();
128 } 155 }
129 } 156 }
130 } 157 }
131 158
132 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 159 /// Queries all impls of the given trait.
133 let fingerprint = TyFingerprint::for_impl(ty); 160 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
134 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied() 161 self.map
135 } 162 .get(&trait_)
136
137 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
138 self.impls_by_trait
139 .get(&tr)
140 .into_iter() 163 .into_iter()
141 .flat_map(|m| m.values().flat_map(|v| v.iter().copied())) 164 .flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
142 } 165 }
143 166
144 pub fn lookup_impl_defs_for_trait_and_ty( 167 /// Queries all impls of `trait_` that may apply to `self_ty`.
168 pub fn for_trait_and_self_ty(
145 &self, 169 &self,
146 tr: TraitId, 170 trait_: TraitId,
147 fp: TyFingerprint, 171 self_ty: TyFingerprint,
148 ) -> impl Iterator<Item = ImplId> + '_ { 172 ) -> impl Iterator<Item = ImplId> + '_ {
149 self.impls_by_trait 173 self.map
150 .get(&tr) 174 .get(&trait_)
151 .and_then(|m| m.get(&Some(fp)))
152 .into_iter() 175 .into_iter()
153 .flatten() 176 .flat_map(move |map| map.get(&None).into_iter().chain(map.get(&Some(self_ty))))
154 .copied() 177 .flat_map(|v| v.iter().copied())
155 .chain( 178 }
156 self.impls_by_trait 179
157 .get(&tr) 180 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
158 .and_then(|m| m.get(&None)) 181 self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
159 .into_iter() 182 }
160 .flatten() 183}
161 .copied(), 184
162 ) 185/// Inherent impls defined in some crate.
186///
187/// Inherent impls can only be defined in the crate that also defines the self type of the impl
188/// (note that some primitives are considered to be defined by both libcore and liballoc).
189///
190/// This makes inherent impl lookup easier than trait impl lookup since we only have to consider a
191/// single crate.
192#[derive(Debug, Eq, PartialEq)]
193pub struct InherentImpls {
194 map: FxHashMap<TyFingerprint, Vec<ImplId>>,
195}
196
197impl InherentImpls {
198 pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
199 let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default();
200
201 let crate_def_map = db.crate_def_map(krate);
202 for (_module_id, module_data) in crate_def_map.modules.iter() {
203 for impl_id in module_data.scope.impls() {
204 let data = db.impl_data(impl_id);
205 if data.target_trait.is_some() {
206 continue;
207 }
208
209 let self_ty = db.impl_self_ty(impl_id);
210 if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) {
211 map.entry(fp).or_default().push(impl_id);
212 }
213 }
214 }
215
216 Arc::new(Self { map })
217 }
218
219 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
220 match TyFingerprint::for_impl(self_ty) {
221 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
222 None => &[],
223 }
163 } 224 }
164 225
165 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 226 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
166 self.inherent_impls 227 self.map.values().flat_map(|v| v.iter().copied())
167 .values()
168 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
169 .flatten()
170 .copied()
171 } 228 }
172} 229}
173 230
@@ -377,7 +434,7 @@ fn iterate_method_candidates_with_autoref(
377 return true; 434 return true;
378 } 435 }
379 let refed = Canonical { 436 let refed = Canonical {
380 num_vars: deref_chain[0].num_vars, 437 kinds: deref_chain[0].kinds.clone(),
381 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 438 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
382 }; 439 };
383 if iterate_method_candidates_by_receiver( 440 if iterate_method_candidates_by_receiver(
@@ -393,7 +450,7 @@ fn iterate_method_candidates_with_autoref(
393 return true; 450 return true;
394 } 451 }
395 let ref_muted = Canonical { 452 let ref_muted = Canonical {
396 num_vars: deref_chain[0].num_vars, 453 kinds: deref_chain[0].kinds.clone(),
397 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 454 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
398 }; 455 };
399 if iterate_method_candidates_by_receiver( 456 if iterate_method_candidates_by_receiver(
@@ -524,9 +581,9 @@ fn iterate_inherent_methods(
524 None => return false, 581 None => return false,
525 }; 582 };
526 for krate in def_crates { 583 for krate in def_crates {
527 let impls = db.impls_in_crate(krate); 584 let impls = db.inherent_impls_in_crate(krate);
528 585
529 for impl_def in impls.lookup_impl_defs(&self_ty.value) { 586 for &impl_def in impls.for_self_ty(&self_ty.value) {
530 for &item in db.impl_data(impl_def).items.iter() { 587 for &item in db.impl_data(impl_def).items.iter() {
531 if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { 588 if !is_valid_candidate(db, name, receiver_ty, item, self_ty) {
532 continue; 589 continue;
@@ -612,18 +669,19 @@ pub(crate) fn inherent_impl_substs(
612 // we create a var for each type parameter of the impl; we need to keep in 669 // we create a var for each type parameter of the impl; we need to keep in
613 // mind here that `self_ty` might have vars of its own 670 // mind here that `self_ty` might have vars of its own
614 let vars = Substs::build_for_def(db, impl_id) 671 let vars = Substs::build_for_def(db, impl_id)
615 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars) 672 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len())
616 .build(); 673 .build();
617 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 674 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
618 let self_ty_with_vars = 675 let mut kinds = self_ty.kinds.to_vec();
619 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; 676 kinds.extend(iter::repeat(TyKind::General).take(vars.len()));
620 let substs = super::infer::unify(&self_ty_with_vars, self_ty); 677 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
678 let substs = super::infer::unify(&tys);
621 // We only want the substs for the vars we added, not the ones from self_ty. 679 // We only want the substs for the vars we added, not the ones from self_ty.
622 // Also, if any of the vars we added are still in there, we replace them by 680 // Also, if any of the vars we added are still in there, we replace them by
623 // Unknown. I think this can only really happen if self_ty contained 681 // Unknown. I think this can only really happen if self_ty contained
624 // Unknown, and in that case we want the result to contain Unknown in those 682 // Unknown, and in that case we want the result to contain Unknown in those
625 // places again. 683 // places again.
626 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.num_vars)) 684 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len()))
627} 685}
628 686
629/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 687/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
@@ -683,15 +741,15 @@ fn generic_implements_goal(
683 trait_: TraitId, 741 trait_: TraitId,
684 self_ty: Canonical<Ty>, 742 self_ty: Canonical<Ty>,
685) -> Canonical<InEnvironment<super::Obligation>> { 743) -> Canonical<InEnvironment<super::Obligation>> {
686 let num_vars = self_ty.num_vars; 744 let mut kinds = self_ty.kinds.to_vec();
687 let substs = super::Substs::build_for_def(db, trait_) 745 let substs = super::Substs::build_for_def(db, trait_)
688 .push(self_ty.value) 746 .push(self_ty.value)
689 .fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars) 747 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
690 .build(); 748 .build();
691 let num_vars = substs.len() - 1 + self_ty.num_vars; 749 kinds.extend(iter::repeat(TyKind::General).take(substs.len() - 1));
692 let trait_ref = TraitRef { trait_, substs }; 750 let trait_ref = TraitRef { trait_, substs };
693 let obligation = super::Obligation::Trait(trait_ref); 751 let obligation = super::Obligation::Trait(trait_ref);
694 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 752 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
695} 753}
696 754
697fn autoderef_method_receiver( 755fn autoderef_method_receiver(
@@ -704,9 +762,9 @@ fn autoderef_method_receiver(
704 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = 762 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) =
705 deref_chain.last().map(|ty| &ty.value) 763 deref_chain.last().map(|ty| &ty.value)
706 { 764 {
707 let num_vars = deref_chain.last().unwrap().num_vars; 765 let kinds = deref_chain.last().unwrap().kinds.clone();
708 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); 766 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone());
709 deref_chain.push(Canonical { value: unsized_ty, num_vars }) 767 deref_chain.push(Canonical { value: unsized_ty, kinds })
710 } 768 }
711 deref_chain 769 deref_chain
712} 770}