aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer/path.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-12-03 12:58:44 +0000
committerGitHub <[email protected]>2019-12-03 12:58:44 +0000
commitc5be0cedf3a9d56c17d988ce6354599b85198fb8 (patch)
tree70e3d0e36efa9568fb7f510f44bd65ff675122a2 /crates/ra_hir_ty/src/infer/path.rs
parent3376c08052a563a5d2db487c458972378edebf44 (diff)
parent18f25acb89304b2eb0a822b7b49b5e66a439ada7 (diff)
Merge #2463
2463: More correct method resolution r=flodiebold a=flodiebold This should fix the order in which candidates for method resolution are considered, i.e. `(&Foo).clone()` should now be of type `Foo` instead of `&Foo`. It also checks for inherent candidates that the self type unifies properly with the self type in the impl (i.e. `impl Foo<u32>` methods will only be considered for `Foo<u32>`). To be able to get the correct receiver type to check in the method resolution, I needed the unification logic, so I extracted it to the `unify.rs` module. Should fix #2435. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/infer/path.rs')
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs42
1 files changed, 5 insertions, 37 deletions
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index bbf146418..b0024c6e1 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -57,7 +57,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
57 let typable: ValueTyDefId = match value { 57 let typable: ValueTyDefId = match value {
58 ValueNs::LocalBinding(pat) => { 58 ValueNs::LocalBinding(pat) => {
59 let ty = self.result.type_of_pat.get(pat)?.clone(); 59 let ty = self.result.type_of_pat.get(pat)?.clone();
60 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 60 let ty = self.resolve_ty_as_possible(ty);
61 return Some(ty); 61 return Some(ty);
62 } 62 }
63 ValueNs::FunctionId(it) => it.into(), 63 ValueNs::FunctionId(it) => it.into(),
@@ -206,12 +206,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
206 AssocItemId::TypeAliasId(_) => unreachable!(), 206 AssocItemId::TypeAliasId(_) => unreachable!(),
207 }; 207 };
208 let substs = match container { 208 let substs = match container {
209 ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()), 209 ContainerId::ImplId(impl_id) => {
210 method_resolution::inherent_impl_substs(self.db, impl_id, &ty)
211 }
210 ContainerId::TraitId(trait_) => { 212 ContainerId::TraitId(trait_) => {
211 // we're picking this method 213 // we're picking this method
212 let trait_substs = Substs::build_for_def(self.db, trait_) 214 let trait_substs = Substs::build_for_def(self.db, trait_)
213 .push(ty.clone()) 215 .push(ty.clone())
214 .fill(std::iter::repeat_with(|| self.new_type_var())) 216 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
215 .build(); 217 .build();
216 let substs = Substs::build_for_def(self.db, item) 218 let substs = Substs::build_for_def(self.db, item)
217 .use_parent_substs(&trait_substs) 219 .use_parent_substs(&trait_substs)
@@ -231,38 +233,4 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
231 }, 233 },
232 ) 234 )
233 } 235 }
234
235 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
236 if let ValueNs::FunctionId(func) = *def {
237 // We only do the infer if parent has generic params
238 let gen = self.db.generic_params(func.into());
239 if gen.count_parent_params() == 0 {
240 return None;
241 }
242
243 let impl_id = match func.lookup(self.db).container {
244 ContainerId::ImplId(it) => it,
245 _ => return None,
246 };
247 let self_ty = self.db.impl_self_ty(impl_id).clone();
248 let self_ty_substs = self_ty.substs()?;
249 let actual_substs = actual_def_ty.substs()?;
250
251 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
252
253 // The following code *link up* the function actual parma type
254 // and impl_block type param index
255 self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
256 if let Ty::Param { idx, .. } = param {
257 if let Some(s) = new_substs.get_mut(*idx as usize) {
258 *s = pty.clone();
259 }
260 }
261 });
262
263 Some(Substs(new_substs.into()))
264 } else {
265 None
266 }
267 }
268} 236}