diff options
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 93 |
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; | |||
9 | use chalk_ir::Mutability; | 9 | use chalk_ir::Mutability; |
10 | use hir_def::{ | 10 | use 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 | }; |
14 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -17,10 +17,11 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
17 | use crate::{ | 17 | use 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`. |
683 | fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { | 696 | fn 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 |