diff options
author | cynecx <[email protected]> | 2021-05-31 19:04:18 +0100 |
---|---|---|
committer | cynecx <[email protected]> | 2021-05-31 19:26:38 +0100 |
commit | 759cb07891d6c9583095d7a1423619b36bc3d547 (patch) | |
tree | c0811e9bd561f44418da38a6ff4ca263ddcb3f3e | |
parent | 7c1d8ca63510bb719fd91bbf38692e45b19c04d6 (diff) |
hir_ty: use correct receiver_ty in method resolution
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 78 |
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, ¶m_tys); | 921 | self.check_call_arguments(args, ¶m_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] | ||
2639 | fn infer_boxed_self_receiver() { | ||
2640 | check_infer( | ||
2641 | r#" | ||
2642 | #[lang = "deref"] | ||
2643 | pub trait Deref { | ||
2644 | type Target; | ||
2645 | fn deref(&self) -> &Self::Target; | ||
2646 | } | ||
2647 | |||
2648 | struct Box<T>(T); | ||
2649 | |||
2650 | impl<T> Deref for Box<T> { | ||
2651 | type Target = T; | ||
2652 | fn deref(&self) -> &Self::Target; | ||
2653 | } | ||
2654 | |||
2655 | struct Foo<T>(T); | ||
2656 | |||
2657 | impl<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 | |||
2665 | fn 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 | } | ||