diff options
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index df5901835..7b0ff8161 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | db::HirDatabase, | 20 | db::HirDatabase, |
21 | primitive::{FloatBitness, Uncertain}, | 21 | primitive::{FloatBitness, Uncertain}, |
22 | utils::all_super_traits, | 22 | utils::all_super_traits, |
23 | Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 23 | ApplicationTy, Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | /// This is used as a key for indexing impls. | 26 | /// This is used as a key for indexing impls. |
@@ -214,7 +214,7 @@ pub fn iterate_method_candidates<T>( | |||
214 | // the methods by autoderef order of *receiver types*, not *self | 214 | // the methods by autoderef order of *receiver types*, not *self |
215 | // types*. | 215 | // types*. |
216 | 216 | ||
217 | let deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); | 217 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
218 | for i in 0..deref_chain.len() { | 218 | for i in 0..deref_chain.len() { |
219 | if let Some(result) = iterate_method_candidates_with_autoref( | 219 | if let Some(result) = iterate_method_candidates_with_autoref( |
220 | &deref_chain[i..], | 220 | &deref_chain[i..], |
@@ -548,3 +548,20 @@ fn generic_implements_goal( | |||
548 | let obligation = super::Obligation::Trait(trait_ref); | 548 | let obligation = super::Obligation::Trait(trait_ref); |
549 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } | 549 | Canonical { num_vars, value: InEnvironment::new(env, obligation) } |
550 | } | 550 | } |
551 | |||
552 | fn autoderef_method_receiver( | ||
553 | db: &impl HirDatabase, | ||
554 | krate: CrateId, | ||
555 | ty: InEnvironment<Canonical<Ty>>, | ||
556 | ) -> Vec<Canonical<Ty>> { | ||
557 | let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); | ||
558 | // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) | ||
559 | if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = | ||
560 | deref_chain.last().map(|ty| &ty.value) | ||
561 | { | ||
562 | let num_vars = deref_chain.last().unwrap().num_vars; | ||
563 | let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); | ||
564 | deref_chain.push(Canonical { value: unsized_ty, num_vars }) | ||
565 | } | ||
566 | deref_chain | ||
567 | } | ||