diff options
author | Florian Diebold <[email protected]> | 2019-12-01 21:14:28 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-12-02 18:33:13 +0000 |
commit | 456d52fdfa8525af2a54e76ee5300f0a40ef582a (patch) | |
tree | e8cd093624ac3ccc9926856dc8db0d4daa0d0b8a /crates/ra_hir_ty/src/method_resolution.rs | |
parent | 599dab59824b164b1c24e2e51adeae1ac1307964 (diff) |
Check receiver type properly
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index fbb932a3e..97281cf15 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -7,19 +7,20 @@ use std::sync::Arc; | |||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, | 9 | lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, |
10 | FunctionId, HasModule, ImplId, TraitId, | 10 | FunctionId, HasModule, ImplId, Lookup, TraitId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
16 | 16 | ||
17 | use super::Substs; | ||
17 | use crate::{ | 18 | use crate::{ |
18 | autoderef, | 19 | autoderef, |
19 | db::HirDatabase, | 20 | db::HirDatabase, |
20 | primitive::{FloatBitness, Uncertain}, | 21 | primitive::{FloatBitness, Uncertain}, |
21 | utils::all_super_traits, | 22 | utils::all_super_traits, |
22 | Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, | 23 | Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | /// This is used as a key for indexing impls. | 26 | /// This is used as a key for indexing impls. |
@@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>( | |||
231 | name: Option<&Name>, | 232 | name: Option<&Name>, |
232 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 233 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
233 | ) -> Option<T> { | 234 | ) -> Option<T> { |
234 | if let Some(result) = iterate_method_candidates_by_receiver(&deref_chain[0], &deref_chain[1..], db, resolver, name, &mut callback) { | 235 | if let Some(result) = iterate_method_candidates_by_receiver( |
236 | &deref_chain[0], | ||
237 | &deref_chain[1..], | ||
238 | db, | ||
239 | resolver, | ||
240 | name, | ||
241 | &mut callback, | ||
242 | ) { | ||
235 | return Some(result); | 243 | return Some(result); |
236 | } | 244 | } |
237 | let refed = Canonical { | 245 | let refed = Canonical { |
238 | num_vars: deref_chain[0].num_vars, | 246 | num_vars: deref_chain[0].num_vars, |
239 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), | 247 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), |
240 | }; | 248 | }; |
241 | if let Some(result) = iterate_method_candidates_by_receiver(&refed, deref_chain, db, resolver, name, &mut callback) { | 249 | if let Some(result) = iterate_method_candidates_by_receiver( |
250 | &refed, | ||
251 | deref_chain, | ||
252 | db, | ||
253 | resolver, | ||
254 | name, | ||
255 | &mut callback, | ||
256 | ) { | ||
242 | return Some(result); | 257 | return Some(result); |
243 | } | 258 | } |
244 | let ref_muted = Canonical { | 259 | let ref_muted = Canonical { |
245 | num_vars: deref_chain[0].num_vars, | 260 | num_vars: deref_chain[0].num_vars, |
246 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), | 261 | value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), |
247 | }; | 262 | }; |
248 | if let Some(result) = iterate_method_candidates_by_receiver(&ref_muted, deref_chain, db, resolver, name, &mut callback) { | 263 | if let Some(result) = iterate_method_candidates_by_receiver( |
264 | &ref_muted, | ||
265 | deref_chain, | ||
266 | db, | ||
267 | resolver, | ||
268 | name, | ||
269 | &mut callback, | ||
270 | ) { | ||
249 | return Some(result); | 271 | return Some(result); |
250 | } | 272 | } |
251 | None | 273 | None |
@@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver<T>( | |||
264 | // be found in any of the derefs of receiver_ty, so we have to go through | 286 | // be found in any of the derefs of receiver_ty, so we have to go through |
265 | // that. | 287 | // that. |
266 | for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { | 288 | for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { |
267 | if let Some(result) = iterate_method_candidates_inner(self_ty, db, resolver, name, Some(receiver_ty), &mut callback) { | 289 | if let Some(result) = iterate_method_candidates_inner( |
290 | self_ty, | ||
291 | db, | ||
292 | resolver, | ||
293 | name, | ||
294 | Some(receiver_ty), | ||
295 | &mut callback, | ||
296 | ) { | ||
268 | return Some(result); | 297 | return Some(result); |
269 | } | 298 | } |
270 | } | 299 | } |
@@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>( | |||
280 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 309 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
281 | ) -> Option<T> { | 310 | ) -> Option<T> { |
282 | let krate = resolver.krate()?; | 311 | let krate = resolver.krate()?; |
283 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) { | 312 | if let Some(result) = |
313 | iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) | ||
314 | { | ||
284 | return Some(result); | 315 | return Some(result); |
285 | } | 316 | } |
286 | if let Some(result) = | 317 | if let Some(result) = |
@@ -381,7 +412,31 @@ fn is_valid_candidate( | |||
381 | if !data.has_self_param { | 412 | if !data.has_self_param { |
382 | return false; | 413 | return false; |
383 | } | 414 | } |
384 | // TODO compare receiver ty | 415 | let substs = match m.lookup(db).container { |
416 | hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, item) | ||
417 | .push(self_ty.value.clone()) | ||
418 | .fill_with_unknown() | ||
419 | .build(), | ||
420 | hir_def::ContainerId::ImplId(impl_id) => { | ||
421 | let vars = | ||
422 | Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); | ||
423 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | ||
424 | let self_ty_with_vars = | ||
425 | Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; | ||
426 | if let Some(substs) = super::infer::unify(self_ty_with_vars, &self_ty.value) | ||
427 | { | ||
428 | substs | ||
429 | } else { | ||
430 | return false; | ||
431 | } | ||
432 | } | ||
433 | hir_def::ContainerId::ModuleId(_) => unreachable!(), | ||
434 | }; | ||
435 | let sig = db.callable_item_signature(m.into()); | ||
436 | let receiver = sig.params()[0].clone().subst(&substs); | ||
437 | if receiver != receiver_ty.value { | ||
438 | return false; | ||
439 | } | ||
385 | } | 440 | } |
386 | true | 441 | true |
387 | } | 442 | } |