aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r--crates/hir_ty/src/method_resolution.rs117
1 files changed, 86 insertions, 31 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index be3e4f09a..48bbcfd9f 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -21,32 +21,36 @@ use crate::{
21 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
22 static_lifetime, 22 static_lifetime,
23 utils::all_super_traits, 23 utils::all_super_traits,
24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, 24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
25 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, 25 Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
26 TyExt, TyKind,
27}; 26};
28 27
29/// This is used as a key for indexing impls. 28/// This is used as a key for indexing impls.
30#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
31pub enum TyFingerprint { 30pub enum TyFingerprint {
31 // These are lang item impls:
32 Str, 32 Str,
33 Slice, 33 Slice,
34 Array, 34 Array,
35 Never, 35 Never,
36 RawPtr(Mutability), 36 RawPtr(Mutability),
37 Scalar(Scalar), 37 Scalar(Scalar),
38 // These can have user-defined impls:
38 Adt(hir_def::AdtId), 39 Adt(hir_def::AdtId),
39 Dyn(TraitId), 40 Dyn(TraitId),
40 Tuple(usize),
41 ForeignType(ForeignDefId), 41 ForeignType(ForeignDefId),
42 FnPtr(usize, FnSig), 42 // These only exist for trait impls
43 Unit,
44 Unnameable,
45 Function(u32),
43} 46}
44 47
45impl TyFingerprint { 48impl TyFingerprint {
46 /// Creates a TyFingerprint for looking up an impl. Only certain types can 49 /// Creates a TyFingerprint for looking up an inherent impl. Only certain
47 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 50 /// types can have inherent impls: if we have some `struct S`, we can have
48 /// `impl &S`. Hence, this will return `None` for reference types and such. 51 /// an `impl S`, but not `impl &S`. Hence, this will return `None` for
49 pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 52 /// reference types and such.
53 pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
50 let fp = match ty.kind(&Interner) { 54 let fp = match ty.kind(&Interner) {
51 TyKind::Str => TyFingerprint::Str, 55 TyKind::Str => TyFingerprint::Str,
52 TyKind::Never => TyFingerprint::Never, 56 TyKind::Never => TyFingerprint::Never,
@@ -54,17 +58,52 @@ impl TyFingerprint {
54 TyKind::Array(..) => TyFingerprint::Array, 58 TyKind::Array(..) => TyFingerprint::Array,
55 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar), 59 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
56 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt), 60 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
57 TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(*cardinality),
58 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability), 61 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
59 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id), 62 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
60 TyKind::Function(FnPointer { sig, substitution: substs, .. }) => {
61 TyFingerprint::FnPtr(substs.0.len(&Interner) - 1, *sig)
62 }
63 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, 63 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
64 _ => return None, 64 _ => return None,
65 }; 65 };
66 Some(fp) 66 Some(fp)
67 } 67 }
68
69 /// Creates a TyFingerprint for looking up a trait impl.
70 pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
71 let fp = match ty.kind(&Interner) {
72 TyKind::Str => TyFingerprint::Str,
73 TyKind::Never => TyFingerprint::Never,
74 TyKind::Slice(..) => TyFingerprint::Slice,
75 TyKind::Array(..) => TyFingerprint::Array,
76 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
77 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
78 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
79 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
80 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
81 TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
82 TyKind::Tuple(_, subst) => {
83 let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(&Interner));
84 if let Some(ty) = first_ty {
85 return TyFingerprint::for_trait_impl(ty);
86 } else {
87 TyFingerprint::Unit
88 }
89 }
90 TyKind::AssociatedType(_, _)
91 | TyKind::OpaqueType(_, _)
92 | TyKind::FnDef(_, _)
93 | TyKind::Closure(_, _)
94 | TyKind::Generator(..)
95 | TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
96 TyKind::Function(fn_ptr) => {
97 TyFingerprint::Function(fn_ptr.substitution.0.len(&Interner) as u32)
98 }
99 TyKind::Alias(_)
100 | TyKind::Placeholder(_)
101 | TyKind::BoundVar(_)
102 | TyKind::InferenceVar(_, _)
103 | TyKind::Error => return None,
104 };
105 Some(fp)
106 }
68} 107}
69 108
70pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ 109pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
@@ -112,7 +151,7 @@ impl TraitImpls {
112 None => continue, 151 None => continue,
113 }; 152 };
114 let self_ty = db.impl_self_ty(impl_id); 153 let self_ty = db.impl_self_ty(impl_id);
115 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); 154 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
116 impls 155 impls
117 .map 156 .map
118 .entry(target_trait) 157 .entry(target_trait)
@@ -157,10 +196,13 @@ impl TraitImpls {
157 } 196 }
158 197
159 /// Queries all trait impls for the given type. 198 /// Queries all trait impls for the given type.
160 pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ { 199 pub fn for_self_ty_without_blanket_impls(
200 &self,
201 fp: TyFingerprint,
202 ) -> impl Iterator<Item = ImplId> + '_ {
161 self.map 203 self.map
162 .values() 204 .values()
163 .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp)))) 205 .flat_map(move |impls| impls.get(&Some(fp)).into_iter())
164 .flat_map(|it| it.iter().copied()) 206 .flat_map(|it| it.iter().copied())
165 } 207 }
166 208
@@ -204,31 +246,43 @@ pub struct InherentImpls {
204 246
205impl InherentImpls { 247impl InherentImpls {
206 pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { 248 pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
207 let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); 249 let mut impls = Self { map: FxHashMap::default() };
208 250
209 let crate_def_map = db.crate_def_map(krate); 251 let crate_def_map = db.crate_def_map(krate);
210 for (_module_id, module_data) in crate_def_map.modules() { 252 collect_def_map(db, &crate_def_map, &mut impls);
211 for impl_id in module_data.scope.impls() { 253
212 let data = db.impl_data(impl_id); 254 return Arc::new(impls);
213 if data.target_trait.is_some() { 255
214 continue; 256 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) {
257 for (_module_id, module_data) in def_map.modules() {
258 for impl_id in module_data.scope.impls() {
259 let data = db.impl_data(impl_id);
260 if data.target_trait.is_some() {
261 continue;
262 }
263
264 let self_ty = db.impl_self_ty(impl_id);
265 let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
266 if let Some(fp) = fp {
267 impls.map.entry(fp).or_default().push(impl_id);
268 }
269 // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
215 } 270 }
216 271
217 let self_ty = db.impl_self_ty(impl_id); 272 // To better support custom derives, collect impls in all unnamed const items.
218 if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) { 273 // const _: () = { ... };
219 map.entry(fp).or_default().push(impl_id); 274 for konst in module_data.scope.unnamed_consts() {
275 let body = db.body(konst.into());
276 for (_, block_def_map) in body.blocks(db.upcast()) {
277 collect_def_map(db, &block_def_map, impls);
278 }
220 } 279 }
221 } 280 }
222 } 281 }
223
224 // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
225 // support trait impls there.
226
227 Arc::new(Self { map })
228 } 282 }
229 283
230 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { 284 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
231 match TyFingerprint::for_impl(self_ty) { 285 match TyFingerprint::for_inherent_impl(self_ty) {
232 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), 286 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
233 None => &[], 287 None => &[],
234 } 288 }
@@ -609,6 +663,7 @@ fn iterate_trait_method_candidates(
609 } 663 }
610 } 664 }
611 known_implemented = true; 665 known_implemented = true;
666 // FIXME: we shouldn't be ignoring the binders here
612 if callback(&self_ty.value, *item) { 667 if callback(&self_ty.value, *item) {
613 return true; 668 return true;
614 } 669 }