aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs21
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs18
2 files changed, 37 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
552fn 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}
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 644d59e17..f9b394f05 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -839,6 +839,24 @@ fn test() { (&S).foo()<|>; }
839} 839}
840 840
841#[test] 841#[test]
842fn method_resolution_unsize_array() {
843 let t = type_at(
844 r#"
845//- /main.rs
846#[lang = "slice"]
847impl<T> [T] {
848 fn len(&self) -> usize { loop {} }
849}
850fn test() {
851 let a = [1, 2, 3];
852 a.len()<|>;
853}
854"#,
855 );
856 assert_eq!(t, "usize");
857}
858
859#[test]
842fn method_resolution_trait_from_prelude() { 860fn method_resolution_trait_from_prelude() {
843 let (db, pos) = TestDB::with_position( 861 let (db, pos) = TestDB::with_position(
844 r#" 862 r#"