aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-02-29 21:01:36 +0000
committerFlorian Diebold <[email protected]>2020-02-29 21:48:53 +0000
commite313efb9926be80a5d7614d800e425b6891cf7d9 (patch)
tree406cf2fa9e725d6eaeef05b825e492651078e6d8
parent5e78036e6c8752fda350818afdd411ab25f405ce (diff)
Do array unsizing for method receivers
It turns out rustc actually only unsizes array method receivers, so we don't need to do any trait solving for this (at least for now). Fixes #2670.
-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#"