diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-03 12:58:44 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-03 12:58:44 +0000 |
commit | c5be0cedf3a9d56c17d988ce6354599b85198fb8 (patch) | |
tree | 70e3d0e36efa9568fb7f510f44bd65ff675122a2 /crates/ra_hir_ty/src/infer/path.rs | |
parent | 3376c08052a563a5d2db487c458972378edebf44 (diff) | |
parent | 18f25acb89304b2eb0a822b7b49b5e66a439ada7 (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.rs | 42 |
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 | } |