aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorcynecx <[email protected]>2021-05-31 19:04:18 +0100
committercynecx <[email protected]>2021-05-31 19:26:38 +0100
commit759cb07891d6c9583095d7a1423619b36bc3d547 (patch)
treec0811e9bd561f44418da38a6ff4ca263ddcb3f3e /crates/hir_ty
parent7c1d8ca63510bb719fd91bbf38692e45b19c04d6 (diff)
hir_ty: use correct receiver_ty in method resolution
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/infer/expr.rs13
-rw-r--r--crates/hir_ty/src/method_resolution.rs3
-rw-r--r--crates/hir_ty/src/tests/simple.rs78
3 files changed, 82 insertions, 12 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 41ef45326..f73bf43b2 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -890,7 +890,7 @@ impl<'a> InferenceContext<'a> {
890 method_name, 890 method_name,
891 ) 891 )
892 }); 892 });
893 let (derefed_receiver_ty, method_ty, substs) = match resolved { 893 let (receiver_ty, method_ty, substs) = match resolved {
894 Some((ty, func)) => { 894 Some((ty, func)) => {
895 let ty = canonicalized_receiver.decanonicalize_ty(ty); 895 let ty = canonicalized_receiver.decanonicalize_ty(ty);
896 let generics = generics(self.db.upcast(), func.into()); 896 let generics = generics(self.db.upcast(), func.into());
@@ -916,16 +916,7 @@ impl<'a> InferenceContext<'a> {
916 } 916 }
917 None => (self.err_ty(), Vec::new(), self.err_ty()), 917 None => (self.err_ty(), Vec::new(), self.err_ty()),
918 }; 918 };
919 // Apply autoref so the below unification works correctly 919 self.unify(&expected_receiver_ty, &receiver_ty);
920 // FIXME: return correct autorefs from lookup_method
921 let actual_receiver_ty = match self.resolve_ty_shallow(&expected_receiver_ty).as_reference()
922 {
923 Some((_, lifetime, mutability)) => {
924 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
925 }
926 _ => derefed_receiver_ty,
927 };
928 self.unify(&expected_receiver_ty, &actual_receiver_ty);
929 920
930 self.check_call_arguments(args, &param_tys); 921 self.check_call_arguments(args, &param_tys);
931 self.normalize_associated_types_in(ret_ty) 922 self.normalize_associated_types_in(ret_ty)
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 08e385a42..af6b6cda7 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -721,7 +721,8 @@ fn iterate_inherent_methods(
721 cov_mark::hit!(impl_self_type_match_without_receiver); 721 cov_mark::hit!(impl_self_type_match_without_receiver);
722 continue; 722 continue;
723 } 723 }
724 if callback(&self_ty.value, item) { 724 let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value);
725 if callback(receiver_ty, item) {
725 return true; 726 return true;
726 } 727 }
727 } 728 }
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 5c70a1fc0..ac312981d 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2634,3 +2634,81 @@ fn f() {
2634 "#]], 2634 "#]],
2635 ) 2635 )
2636} 2636}
2637
2638#[test]
2639fn infer_boxed_self_receiver() {
2640 check_infer(
2641 r#"
2642#[lang = "deref"]
2643pub trait Deref {
2644 type Target;
2645 fn deref(&self) -> &Self::Target;
2646}
2647
2648struct Box<T>(T);
2649
2650impl<T> Deref for Box<T> {
2651 type Target = T;
2652 fn deref(&self) -> &Self::Target;
2653}
2654
2655struct Foo<T>(T);
2656
2657impl<T> Foo<T> {
2658 fn get_inner<'a>(self: &'a Box<Self>) -> &'a T {}
2659
2660 fn get_self<'a>(self: &'a Box<Self>) -> &'a Self {}
2661
2662 fn into_inner(self: Box<Self>) -> Self {}
2663}
2664
2665fn main() {
2666 let boxed = Box(Foo(0_i32));
2667
2668 let bad1 = boxed.get_inner();
2669 let good1 = Foo::get_inner(&boxed);
2670
2671 let bad2 = boxed.get_self();
2672 let good2 = Foo::get_self(&boxed);
2673
2674 let inner = boxed.into_inner();
2675}
2676 "#,
2677 expect![[r#"
2678 67..71 'self': &Self
2679 175..179 'self': &Box<T>
2680 259..263 'self': &Box<Foo<T>>
2681 289..291 '{}': ()
2682 313..317 'self': &Box<Foo<T>>
2683 346..348 '{}': ()
2684 368..372 'self': Box<Foo<T>>
2685 393..395 '{}': ()
2686 409..630 '{ ...r(); }': ()
2687 419..424 'boxed': Box<Foo<i32>>
2688 427..430 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
2689 427..442 'Box(Foo(0_i32))': Box<Foo<i32>>
2690 431..434 'Foo': Foo<i32>(i32) -> Foo<i32>
2691 431..441 'Foo(0_i32)': Foo<i32>
2692 435..440 '0_i32': i32
2693 453..457 'bad1': &i32
2694 460..465 'boxed': Box<Foo<i32>>
2695 460..477 'boxed....nner()': &i32
2696 487..492 'good1': &i32
2697 495..509 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
2698 495..517 'Foo::g...boxed)': &i32
2699 510..516 '&boxed': &Box<Foo<i32>>
2700 511..516 'boxed': Box<Foo<i32>>
2701 528..532 'bad2': &Foo<i32>
2702 535..540 'boxed': Box<Foo<i32>>
2703 535..551 'boxed....self()': &Foo<i32>
2704 561..566 'good2': &Foo<i32>
2705 569..582 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
2706 569..590 'Foo::g...boxed)': &Foo<i32>
2707 583..589 '&boxed': &Box<Foo<i32>>
2708 584..589 'boxed': Box<Foo<i32>>
2709 601..606 'inner': Foo<i32>
2710 609..614 'boxed': Box<Foo<i32>>
2711 609..627 'boxed....nner()': Foo<i32>
2712 "#]],
2713 );
2714}