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.rs93
1 files changed, 54 insertions, 39 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index d57c6de70..be72c4a1c 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -9,7 +9,7 @@ use base_db::CrateId;
9use chalk_ir::Mutability; 9use chalk_ir::Mutability;
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
12 ImplId, Lookup, ModuleId, TraitId, TypeAliasId, 12 ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
@@ -17,10 +17,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef,
19 db::HirDatabase, 19 db::HirDatabase,
20 from_foreign_def_id,
20 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
21 utils::all_super_traits, 22 utils::all_super_traits,
22 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, 23 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner,
23 TraitEnvironment, TraitRef, Ty, TypeWalk, 24 Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
24}; 25};
25 26
26/// This is used as a key for indexing impls. 27/// This is used as a key for indexing impls.
@@ -35,7 +36,7 @@ pub enum TyFingerprint {
35 Adt(hir_def::AdtId), 36 Adt(hir_def::AdtId),
36 Dyn(TraitId), 37 Dyn(TraitId),
37 Tuple(usize), 38 Tuple(usize),
38 ForeignType(TypeAliasId), 39 ForeignType(ForeignDefId),
39 FnPtr(usize, FnSig), 40 FnPtr(usize, FnSig),
40} 41}
41 42
@@ -43,19 +44,21 @@ impl TyFingerprint {
43 /// Creates a TyFingerprint for looking up an impl. Only certain types can 44 /// Creates a TyFingerprint for looking up an impl. Only certain types can
44 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 45 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
45 /// `impl &S`. Hence, this will return `None` for reference types and such. 46 /// `impl &S`. Hence, this will return `None` for reference types and such.
46 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 47 pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
47 let fp = match ty { 48 let fp = match *ty.interned(&Interner) {
48 &Ty::Str => TyFingerprint::Str, 49 TyKind::Str => TyFingerprint::Str,
49 &Ty::Never => TyFingerprint::Never, 50 TyKind::Never => TyFingerprint::Never,
50 &Ty::Slice(..) => TyFingerprint::Slice, 51 TyKind::Slice(..) => TyFingerprint::Slice,
51 &Ty::Array(..) => TyFingerprint::Array, 52 TyKind::Array(..) => TyFingerprint::Array,
52 &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), 53 TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar),
53 &Ty::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), 54 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt),
54 &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), 55 TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
55 &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), 56 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
56 &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), 57 TyKind::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
57 &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig), 58 TyKind::Function(FnPointer { num_args, sig, .. }) => {
58 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, 59 TyFingerprint::FnPtr(num_args, sig)
60 }
61 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
59 _ => return None, 62 _ => return None,
60 }; 63 };
61 Some(fp) 64 Some(fp)
@@ -138,6 +141,14 @@ impl TraitImpls {
138 } 141 }
139 } 142 }
140 143
144 /// Queries all trait impls for the given type.
145 pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ {
146 self.map
147 .values()
148 .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp))))
149 .flat_map(|it| it.iter().copied())
150 }
151
141 /// Queries all impls of the given trait. 152 /// Queries all impls of the given trait.
142 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ { 153 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
143 self.map 154 self.map
@@ -230,31 +241,33 @@ impl Ty {
230 241
231 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); 242 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
232 243
233 let lang_item_targets = match self { 244 let lang_item_targets = match self.interned(&Interner) {
234 Ty::Adt(AdtId(def_id), _) => { 245 TyKind::Adt(AdtId(def_id), _) => {
235 return mod_to_crate_ids(def_id.module(db.upcast())); 246 return mod_to_crate_ids(def_id.module(db.upcast()));
236 } 247 }
237 Ty::ForeignType(type_alias_id) => { 248 TyKind::ForeignType(id) => {
238 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast())); 249 return mod_to_crate_ids(
250 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()),
251 );
239 } 252 }
240 Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"), 253 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
241 Ty::Scalar(Scalar::Char) => lang_item_crate!("char"), 254 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
242 Ty::Scalar(Scalar::Float(f)) => match f { 255 TyKind::Scalar(Scalar::Float(f)) => match f {
243 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 256 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
244 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), 257 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
245 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), 258 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
246 }, 259 },
247 &Ty::Scalar(Scalar::Int(t)) => { 260 &TyKind::Scalar(Scalar::Int(t)) => {
248 lang_item_crate!(primitive::int_ty_to_string(t)) 261 lang_item_crate!(primitive::int_ty_to_string(t))
249 } 262 }
250 &Ty::Scalar(Scalar::Uint(t)) => { 263 &TyKind::Scalar(Scalar::Uint(t)) => {
251 lang_item_crate!(primitive::uint_ty_to_string(t)) 264 lang_item_crate!(primitive::uint_ty_to_string(t))
252 } 265 }
253 Ty::Str => lang_item_crate!("str_alloc", "str"), 266 TyKind::Str => lang_item_crate!("str_alloc", "str"),
254 Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), 267 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
255 Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), 268 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
256 Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), 269 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
257 Ty::Dyn(_) => { 270 TyKind::Dyn(_) => {
258 return self.dyn_trait().and_then(|trait_| { 271 return self.dyn_trait().and_then(|trait_| {
259 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) 272 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
260 }); 273 });
@@ -430,7 +443,7 @@ fn iterate_method_candidates_with_autoref(
430 } 443 }
431 let refed = Canonical { 444 let refed = Canonical {
432 kinds: deref_chain[0].kinds.clone(), 445 kinds: deref_chain[0].kinds.clone(),
433 value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())), 446 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
434 }; 447 };
435 if iterate_method_candidates_by_receiver( 448 if iterate_method_candidates_by_receiver(
436 &refed, 449 &refed,
@@ -446,7 +459,7 @@ fn iterate_method_candidates_with_autoref(
446 } 459 }
447 let ref_muted = Canonical { 460 let ref_muted = Canonical {
448 kinds: deref_chain[0].kinds.clone(), 461 kinds: deref_chain[0].kinds.clone(),
449 value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())), 462 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
450 }; 463 };
451 if iterate_method_candidates_by_receiver( 464 if iterate_method_candidates_by_receiver(
452 &ref_muted, 465 &ref_muted,
@@ -526,7 +539,7 @@ fn iterate_trait_method_candidates(
526 // if ty is `dyn Trait`, the trait doesn't need to be in scope 539 // if ty is `dyn Trait`, the trait doesn't need to be in scope
527 let inherent_trait = 540 let inherent_trait =
528 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); 541 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
529 let env_traits = if let Ty::Placeholder(_) = self_ty.value { 542 let env_traits = if let TyKind::Placeholder(_) = self_ty.value.interned(&Interner) {
530 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 543 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
531 env.traits_in_scope_from_clauses(&self_ty.value) 544 env.traits_in_scope_from_clauses(&self_ty.value)
532 .flat_map(|t| all_super_traits(db.upcast(), t)) 545 .flat_map(|t| all_super_traits(db.upcast(), t))
@@ -679,13 +692,13 @@ pub(crate) fn inherent_impl_substs(
679} 692}
680 693
681/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 694/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
682/// num_vars_to_keep) by `Ty::Unknown`. 695/// num_vars_to_keep) by `TyKind::Unknown`.
683fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 696fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
684 s.fold_binders( 697 s.fold_binders(
685 &mut |ty, binders| { 698 &mut |ty, binders| {
686 if let Ty::BoundVar(bound) = &ty { 699 if let TyKind::BoundVar(bound) = ty.interned(&Interner) {
687 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 700 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
688 Ty::Unknown 701 TyKind::Unknown.intern(&Interner)
689 } else { 702 } else {
690 ty 703 ty
691 } 704 }
@@ -772,9 +785,11 @@ fn autoderef_method_receiver(
772) -> Vec<Canonical<Ty>> { 785) -> Vec<Canonical<Ty>> {
773 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 786 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
774 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 787 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
775 if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) { 788 if let Some(TyKind::Array(parameters)) =
789 deref_chain.last().map(|ty| ty.value.interned(&Interner))
790 {
776 let kinds = deref_chain.last().unwrap().kinds.clone(); 791 let kinds = deref_chain.last().unwrap().kinds.clone();
777 let unsized_ty = Ty::Slice(parameters.clone()); 792 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
778 deref_chain.push(Canonical { value: unsized_ty, kinds }) 793 deref_chain.push(Canonical { value: unsized_ty, kinds })
779 } 794 }
780 deref_chain 795 deref_chain