aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/method_resolution.rs
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 /crates/ra_hir_ty/src/method_resolution.rs
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.
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs21
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
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}