diff options
author | Florian Diebold <[email protected]> | 2020-02-29 21:01:36 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-02-29 21:48:53 +0000 |
commit | e313efb9926be80a5d7614d800e425b6891cf7d9 (patch) | |
tree | 406cf2fa9e725d6eaeef05b825e492651078e6d8 /crates | |
parent | 5e78036e6c8752fda350818afdd411ab25f405ce (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.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 18 |
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 | |||
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 | } | ||
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] |
842 | fn method_resolution_unsize_array() { | ||
843 | let t = type_at( | ||
844 | r#" | ||
845 | //- /main.rs | ||
846 | #[lang = "slice"] | ||
847 | impl<T> [T] { | ||
848 | fn len(&self) -> usize { loop {} } | ||
849 | } | ||
850 | fn test() { | ||
851 | let a = [1, 2, 3]; | ||
852 | a.len()<|>; | ||
853 | } | ||
854 | "#, | ||
855 | ); | ||
856 | assert_eq!(t, "usize"); | ||
857 | } | ||
858 | |||
859 | #[test] | ||
842 | fn method_resolution_trait_from_prelude() { | 860 | fn method_resolution_trait_from_prelude() { |
843 | let (db, pos) = TestDB::with_position( | 861 | let (db, pos) = TestDB::with_position( |
844 | r#" | 862 | r#" |