diff options
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 186 |
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 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | ||
9 | use hir_def::{ | 10 | use 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 | }; |
15 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
16 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
17 | 16 | ||
18 | use super::Substs; | ||
19 | use crate::{ | 17 | use 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)] |
30 | pub enum TyFingerprint { | 28 | pub 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 | ||
34 | impl TyFingerprint { | 42 | impl 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 | ||
46 | pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ | 65 | pub(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 | ||
97 | pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ | 80 | pub(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). |
290 | pub(crate) fn lookup_method( | 278 | pub(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( | |||
696 | fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { | 684 | fn 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 |