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.rs186
1 files changed, 86 insertions, 100 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 8a289f52a..f301a8477 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -6,29 +6,37 @@ use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::Mutability;
9use hir_def::{ 10use hir_def::{
10 builtin_type::{IntBitness, Signedness}, 11 lang_item::LangItemTarget, AdtId, AssocContainerId, AssocItemId, FunctionId, GenericDefId,
11 lang_item::LangItemTarget, 12 HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId,
12 type_ref::Mutability,
13 AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
14}; 13};
15use hir_expand::name::Name; 14use hir_expand::name::Name;
16use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
17 16
18use super::Substs;
19use crate::{ 17use crate::{
20 autoderef, 18 autoderef,
21 db::HirDatabase, 19 db::HirDatabase,
22 primitive::{FloatBitness, FloatTy, IntTy}, 20 primitive::{self, FloatTy, IntTy, UintTy},
23 utils::all_super_traits, 21 utils::all_super_traits,
24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, 22 Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, TraitEnvironment,
25 TypeCtor, TypeWalk, 23 TraitRef, Ty, TypeWalk,
26}; 24};
27 25
28/// This is used as a key for indexing impls. 26/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 28pub enum TyFingerprint {
31 Apply(TypeCtor), 29 Str,
30 Slice,
31 Array,
32 Never,
33 RawPtr(Mutability),
34 Scalar(Scalar),
35 Adt(AdtId),
36 Dyn(TraitId),
37 Tuple(usize),
38 ForeignType(TypeAliasId),
39 FnPtr(usize, FnSig),
32} 40}
33 41
34impl TyFingerprint { 42impl TyFingerprint {
@@ -36,67 +44,42 @@ impl TyFingerprint {
36 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 44 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
37 /// `impl &S`. Hence, this will return `None` for reference types and such. 45 /// `impl &S`. Hence, this will return `None` for reference types and such.
38 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 46 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
39 match ty { 47 let fp = match ty {
40 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), 48 &Ty::Str => TyFingerprint::Str,
41 _ => None, 49 &Ty::Never => TyFingerprint::Never,
42 } 50 &Ty::Slice(..) => TyFingerprint::Slice,
51 &Ty::Array(..) => TyFingerprint::Array,
52 &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar),
53 &Ty::Adt(adt, _) => TyFingerprint::Adt(adt),
54 &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality),
55 &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability),
56 &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
57 &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig),
58 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
59 _ => return None,
60 };
61 Some(fp)
43 } 62 }
44} 63}
45 64
46pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ 65pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
47 TyFingerprint::Apply(TypeCtor::Int(IntTy { 66 TyFingerprint::Scalar(Scalar::Int(IntTy::I8)),
48 signedness: Signedness::Unsigned, 67 TyFingerprint::Scalar(Scalar::Int(IntTy::I16)),
49 bitness: IntBitness::X8, 68 TyFingerprint::Scalar(Scalar::Int(IntTy::I32)),
50 })), 69 TyFingerprint::Scalar(Scalar::Int(IntTy::I64)),
51 TyFingerprint::Apply(TypeCtor::Int(IntTy { 70 TyFingerprint::Scalar(Scalar::Int(IntTy::I128)),
52 signedness: Signedness::Unsigned, 71 TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)),
53 bitness: IntBitness::X16, 72 TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)),
54 })), 73 TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)),
55 TyFingerprint::Apply(TypeCtor::Int(IntTy { 74 TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)),
56 signedness: Signedness::Unsigned, 75 TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)),
57 bitness: IntBitness::X32, 76 TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)),
58 })), 77 TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
59 TyFingerprint::Apply(TypeCtor::Int(IntTy {
60 signedness: Signedness::Unsigned,
61 bitness: IntBitness::X64,
62 })),
63 TyFingerprint::Apply(TypeCtor::Int(IntTy {
64 signedness: Signedness::Unsigned,
65 bitness: IntBitness::X128,
66 })),
67 TyFingerprint::Apply(TypeCtor::Int(IntTy {
68 signedness: Signedness::Unsigned,
69 bitness: IntBitness::Xsize,
70 })),
71 TyFingerprint::Apply(TypeCtor::Int(IntTy {
72 signedness: Signedness::Signed,
73 bitness: IntBitness::X8,
74 })),
75 TyFingerprint::Apply(TypeCtor::Int(IntTy {
76 signedness: Signedness::Signed,
77 bitness: IntBitness::X16,
78 })),
79 TyFingerprint::Apply(TypeCtor::Int(IntTy {
80 signedness: Signedness::Signed,
81 bitness: IntBitness::X32,
82 })),
83 TyFingerprint::Apply(TypeCtor::Int(IntTy {
84 signedness: Signedness::Signed,
85 bitness: IntBitness::X64,
86 })),
87 TyFingerprint::Apply(TypeCtor::Int(IntTy {
88 signedness: Signedness::Signed,
89 bitness: IntBitness::X128,
90 })),
91 TyFingerprint::Apply(TypeCtor::Int(IntTy {
92 signedness: Signedness::Signed,
93 bitness: IntBitness::Xsize,
94 })),
95]; 78];
96 79
97pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ 80pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
98 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })), 81 TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
99 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })), 82 TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
100]; 83];
101 84
102/// Trait impls defined or available in some crate. 85/// Trait impls defined or available in some crate.
@@ -112,7 +95,7 @@ impl TraitImpls {
112 let mut impls = Self { map: FxHashMap::default() }; 95 let mut impls = Self { map: FxHashMap::default() };
113 96
114 let crate_def_map = db.crate_def_map(krate); 97 let crate_def_map = db.crate_def_map(krate);
115 for (_module_id, module_data) in crate_def_map.modules.iter() { 98 for (_module_id, module_data) in crate_def_map.modules() {
116 for impl_id in module_data.scope.impls() { 99 for impl_id in module_data.scope.impls() {
117 let target_trait = match db.impl_trait(impl_id) { 100 let target_trait = match db.impl_trait(impl_id) {
118 Some(tr) => tr.value.trait_, 101 Some(tr) => tr.value.trait_,
@@ -198,7 +181,7 @@ impl InherentImpls {
198 let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); 181 let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default();
199 182
200 let crate_def_map = db.crate_def_map(krate); 183 let crate_def_map = db.crate_def_map(krate);
201 for (_module_id, module_data) in crate_def_map.modules.iter() { 184 for (_module_id, module_data) in crate_def_map.modules() {
202 for impl_id in module_data.scope.impls() { 185 for impl_id in module_data.scope.impls() {
203 let data = db.impl_data(impl_id); 186 let data = db.impl_data(impl_id);
204 if data.target_trait.is_some() { 187 if data.target_trait.is_some() {
@@ -245,33 +228,37 @@ impl Ty {
245 }}; 228 }};
246 } 229 }
247 230
231 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
232
248 let lang_item_targets = match self { 233 let lang_item_targets = match self {
249 Ty::Apply(a_ty) => match a_ty.ctor { 234 Ty::Adt(def_id, _) => {
250 TypeCtor::Adt(def_id) => { 235 return mod_to_crate_ids(def_id.module(db.upcast()));
251 return Some(std::iter::once(def_id.module(db.upcast()).krate).collect()) 236 }
252 } 237 Ty::ForeignType(type_alias_id) => {
253 TypeCtor::ForeignType(type_alias_id) => { 238 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
254 return Some( 239 }
255 std::iter::once( 240 Ty::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
256 type_alias_id.lookup(db.upcast()).module(db.upcast()).krate, 241 Ty::Scalar(Scalar::Char) => lang_item_crate!("char"),
257 ) 242 Ty::Scalar(Scalar::Float(f)) => match f {
258 .collect(), 243 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
259 ) 244 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
260 } 245 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
261 TypeCtor::Bool => lang_item_crate!("bool"),
262 TypeCtor::Char => lang_item_crate!("char"),
263 TypeCtor::Float(f) => match f.bitness {
264 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
265 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
266 FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
267 },
268 TypeCtor::Int(i) => lang_item_crate!(i.ty_to_string()),
269 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
270 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
271 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
272 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
273 _ => return None,
274 }, 246 },
247 &Ty::Scalar(Scalar::Int(t)) => {
248 lang_item_crate!(primitive::int_ty_to_string(t))
249 }
250 &Ty::Scalar(Scalar::Uint(t)) => {
251 lang_item_crate!(primitive::uint_ty_to_string(t))
252 }
253 Ty::Str => lang_item_crate!("str_alloc", "str"),
254 Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
255 Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
256 Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
257 Ty::Dyn(_) => {
258 return self.dyn_trait().and_then(|trait_| {
259 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
260 });
261 }
275 _ => return None, 262 _ => return None,
276 }; 263 };
277 let res = lang_item_targets 264 let res = lang_item_targets
@@ -280,11 +267,12 @@ impl Ty {
280 LangItemTarget::ImplDefId(it) => Some(it), 267 LangItemTarget::ImplDefId(it) => Some(it),
281 _ => None, 268 _ => None,
282 }) 269 })
283 .map(|it| it.lookup(db.upcast()).container.module(db.upcast()).krate) 270 .map(|it| it.lookup(db.upcast()).container.module(db.upcast()).krate())
284 .collect(); 271 .collect();
285 Some(res) 272 Some(res)
286 } 273 }
287} 274}
275
288/// Look up the method with the given name, returning the actual autoderefed 276/// Look up the method with the given name, returning the actual autoderefed
289/// receiver type (but without autoref applied yet). 277/// receiver type (but without autoref applied yet).
290pub(crate) fn lookup_method( 278pub(crate) fn lookup_method(
@@ -442,7 +430,7 @@ fn iterate_method_candidates_with_autoref(
442 } 430 }
443 let refed = Canonical { 431 let refed = Canonical {
444 kinds: deref_chain[0].kinds.clone(), 432 kinds: deref_chain[0].kinds.clone(),
445 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 433 value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())),
446 }; 434 };
447 if iterate_method_candidates_by_receiver( 435 if iterate_method_candidates_by_receiver(
448 &refed, 436 &refed,
@@ -458,7 +446,7 @@ fn iterate_method_candidates_with_autoref(
458 } 446 }
459 let ref_muted = Canonical { 447 let ref_muted = Canonical {
460 kinds: deref_chain[0].kinds.clone(), 448 kinds: deref_chain[0].kinds.clone(),
461 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 449 value: Ty::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())),
462 }; 450 };
463 if iterate_method_candidates_by_receiver( 451 if iterate_method_candidates_by_receiver(
464 &ref_muted, 452 &ref_muted,
@@ -680,7 +668,7 @@ pub(crate) fn inherent_impl_substs(
680 .build(); 668 .build();
681 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 669 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
682 let mut kinds = self_ty.kinds.to_vec(); 670 let mut kinds = self_ty.kinds.to_vec();
683 kinds.extend(iter::repeat(TyKind::General).take(vars.len())); 671 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len()));
684 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; 672 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
685 let substs = super::infer::unify(&tys); 673 let substs = super::infer::unify(&tys);
686 // We only want the substs for the vars we added, not the ones from self_ty. 674 // We only want the substs for the vars we added, not the ones from self_ty.
@@ -696,7 +684,7 @@ pub(crate) fn inherent_impl_substs(
696fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 684fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
697 s.fold_binders( 685 s.fold_binders(
698 &mut |ty, binders| { 686 &mut |ty, binders| {
699 if let Ty::Bound(bound) = &ty { 687 if let Ty::BoundVar(bound) = &ty {
700 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 688 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
701 Ty::Unknown 689 Ty::Unknown
702 } else { 690 } else {
@@ -772,7 +760,7 @@ fn generic_implements_goal(
772 .push(self_ty.value) 760 .push(self_ty.value)
773 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) 761 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
774 .build(); 762 .build();
775 kinds.extend(iter::repeat(TyKind::General).take(substs.len() - 1)); 763 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
776 let trait_ref = TraitRef { trait_, substs }; 764 let trait_ref = TraitRef { trait_, substs };
777 let obligation = super::Obligation::Trait(trait_ref); 765 let obligation = super::Obligation::Trait(trait_ref);
778 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } 766 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
@@ -785,11 +773,9 @@ fn autoderef_method_receiver(
785) -> Vec<Canonical<Ty>> { 773) -> Vec<Canonical<Ty>> {
786 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 774 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
787 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 775 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
788 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = 776 if let Some(Ty::Array(parameters)) = deref_chain.last().map(|ty| &ty.value) {
789 deref_chain.last().map(|ty| &ty.value)
790 {
791 let kinds = deref_chain.last().unwrap().kinds.clone(); 777 let kinds = deref_chain.last().unwrap().kinds.clone();
792 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); 778 let unsized_ty = Ty::Slice(parameters.clone());
793 deref_chain.push(Canonical { value: unsized_ty, kinds }) 779 deref_chain.push(Canonical { value: unsized_ty, kinds })
794 } 780 }
795 deref_chain 781 deref_chain