diff options
Diffstat (limited to 'crates/ra_hir_ty/src/tests/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 158 |
1 files changed, 68 insertions, 90 deletions
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 20329bae4..9c8f22314 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use super::{infer, type_at, type_at_pos}; | ||
2 | use crate::test_db::TestDB; | ||
3 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
4 | use ra_db::fixture::WithFixture; | 2 | |
3 | use super::{check_types, infer}; | ||
5 | 4 | ||
6 | #[test] | 5 | #[test] |
7 | fn infer_slice_method() { | 6 | fn infer_slice_method() { |
@@ -246,13 +245,13 @@ fn test() { | |||
246 | 245 | ||
247 | #[test] | 246 | #[test] |
248 | fn cross_crate_associated_method_call() { | 247 | fn cross_crate_associated_method_call() { |
249 | let (db, pos) = TestDB::with_position( | 248 | check_types( |
250 | r#" | 249 | r#" |
251 | //- /main.rs crate:main deps:other_crate | 250 | //- /main.rs crate:main deps:other_crate |
252 | fn test() { | 251 | fn test() { |
253 | let x = other_crate::foo::S::thing(); | 252 | let x = other_crate::foo::S::thing(); |
254 | x<|>; | 253 | x; |
255 | } | 254 | } //^ i128 |
256 | 255 | ||
257 | //- /lib.rs crate:other_crate | 256 | //- /lib.rs crate:other_crate |
258 | mod foo { | 257 | mod foo { |
@@ -263,7 +262,6 @@ mod foo { | |||
263 | } | 262 | } |
264 | "#, | 263 | "#, |
265 | ); | 264 | ); |
266 | assert_eq!("i128", type_at_pos(&db, pos)); | ||
267 | } | 265 | } |
268 | 266 | ||
269 | #[test] | 267 | #[test] |
@@ -684,135 +682,127 @@ fn test() { | |||
684 | 682 | ||
685 | #[test] | 683 | #[test] |
686 | fn method_resolution_unify_impl_self_type() { | 684 | fn method_resolution_unify_impl_self_type() { |
687 | let t = type_at( | 685 | check_types( |
688 | r#" | 686 | r#" |
689 | //- /main.rs | ||
690 | struct S<T>; | 687 | struct S<T>; |
691 | impl S<u32> { fn foo(&self) -> u8 {} } | 688 | impl S<u32> { fn foo(&self) -> u8 {} } |
692 | impl S<i32> { fn foo(&self) -> i8 {} } | 689 | impl S<i32> { fn foo(&self) -> i8 {} } |
693 | fn test() { (S::<u32>.foo(), S::<i32>.foo())<|>; } | 690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } |
691 | //^ (u8, i8) | ||
694 | "#, | 692 | "#, |
695 | ); | 693 | ); |
696 | assert_eq!(t, "(u8, i8)"); | ||
697 | } | 694 | } |
698 | 695 | ||
699 | #[test] | 696 | #[test] |
700 | fn method_resolution_trait_before_autoref() { | 697 | fn method_resolution_trait_before_autoref() { |
701 | let t = type_at( | 698 | check_types( |
702 | r#" | 699 | r#" |
703 | //- /main.rs | ||
704 | trait Trait { fn foo(self) -> u128; } | 700 | trait Trait { fn foo(self) -> u128; } |
705 | struct S; | 701 | struct S; |
706 | impl S { fn foo(&self) -> i8 { 0 } } | 702 | impl S { fn foo(&self) -> i8 { 0 } } |
707 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 703 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
708 | fn test() { S.foo()<|>; } | 704 | fn test() { S.foo(); } |
705 | //^ u128 | ||
709 | "#, | 706 | "#, |
710 | ); | 707 | ); |
711 | assert_eq!(t, "u128"); | ||
712 | } | 708 | } |
713 | 709 | ||
714 | #[test] | 710 | #[test] |
715 | fn method_resolution_by_value_before_autoref() { | 711 | fn method_resolution_by_value_before_autoref() { |
716 | let t = type_at( | 712 | check_types( |
717 | r#" | 713 | r#" |
718 | //- /main.rs | ||
719 | trait Clone { fn clone(&self) -> Self; } | 714 | trait Clone { fn clone(&self) -> Self; } |
720 | struct S; | 715 | struct S; |
721 | impl Clone for S {} | 716 | impl Clone for S {} |
722 | impl Clone for &S {} | 717 | impl Clone for &S {} |
723 | fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; } | 718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } |
719 | //^ (S, S, &S) | ||
724 | "#, | 720 | "#, |
725 | ); | 721 | ); |
726 | assert_eq!(t, "(S, S, &S)"); | ||
727 | } | 722 | } |
728 | 723 | ||
729 | #[test] | 724 | #[test] |
730 | fn method_resolution_trait_before_autoderef() { | 725 | fn method_resolution_trait_before_autoderef() { |
731 | let t = type_at( | 726 | check_types( |
732 | r#" | 727 | r#" |
733 | //- /main.rs | ||
734 | trait Trait { fn foo(self) -> u128; } | 728 | trait Trait { fn foo(self) -> u128; } |
735 | struct S; | 729 | struct S; |
736 | impl S { fn foo(self) -> i8 { 0 } } | 730 | impl S { fn foo(self) -> i8 { 0 } } |
737 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
738 | fn test() { (&S).foo()<|>; } | 732 | fn test() { (&S).foo(); } |
733 | //^ u128 | ||
739 | "#, | 734 | "#, |
740 | ); | 735 | ); |
741 | assert_eq!(t, "u128"); | ||
742 | } | 736 | } |
743 | 737 | ||
744 | #[test] | 738 | #[test] |
745 | fn method_resolution_impl_before_trait() { | 739 | fn method_resolution_impl_before_trait() { |
746 | let t = type_at( | 740 | check_types( |
747 | r#" | 741 | r#" |
748 | //- /main.rs | ||
749 | trait Trait { fn foo(self) -> u128; } | 742 | trait Trait { fn foo(self) -> u128; } |
750 | struct S; | 743 | struct S; |
751 | impl S { fn foo(self) -> i8 { 0 } } | 744 | impl S { fn foo(self) -> i8 { 0 } } |
752 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 745 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
753 | fn test() { S.foo()<|>; } | 746 | fn test() { S.foo(); } |
747 | //^ i8 | ||
754 | "#, | 748 | "#, |
755 | ); | 749 | ); |
756 | assert_eq!(t, "i8"); | ||
757 | } | 750 | } |
758 | 751 | ||
759 | #[test] | 752 | #[test] |
760 | fn method_resolution_impl_ref_before_trait() { | 753 | fn method_resolution_impl_ref_before_trait() { |
761 | let t = type_at( | 754 | check_types( |
762 | r#" | 755 | r#" |
763 | //- /main.rs | ||
764 | trait Trait { fn foo(self) -> u128; } | 756 | trait Trait { fn foo(self) -> u128; } |
765 | struct S; | 757 | struct S; |
766 | impl S { fn foo(&self) -> i8 { 0 } } | 758 | impl S { fn foo(&self) -> i8 { 0 } } |
767 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
768 | fn test() { S.foo()<|>; } | 760 | fn test() { S.foo(); } |
761 | //^ i8 | ||
769 | "#, | 762 | "#, |
770 | ); | 763 | ); |
771 | assert_eq!(t, "i8"); | ||
772 | } | 764 | } |
773 | 765 | ||
774 | #[test] | 766 | #[test] |
775 | fn method_resolution_trait_autoderef() { | 767 | fn method_resolution_trait_autoderef() { |
776 | let t = type_at( | 768 | check_types( |
777 | r#" | 769 | r#" |
778 | //- /main.rs | ||
779 | trait Trait { fn foo(self) -> u128; } | 770 | trait Trait { fn foo(self) -> u128; } |
780 | struct S; | 771 | struct S; |
781 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 772 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
782 | fn test() { (&S).foo()<|>; } | 773 | fn test() { (&S).foo(); } |
774 | //^ u128 | ||
783 | "#, | 775 | "#, |
784 | ); | 776 | ); |
785 | assert_eq!(t, "u128"); | ||
786 | } | 777 | } |
787 | 778 | ||
788 | #[test] | 779 | #[test] |
789 | fn method_resolution_unsize_array() { | 780 | fn method_resolution_unsize_array() { |
790 | let t = type_at( | 781 | check_types( |
791 | r#" | 782 | r#" |
792 | //- /main.rs | ||
793 | #[lang = "slice"] | 783 | #[lang = "slice"] |
794 | impl<T> [T] { | 784 | impl<T> [T] { |
795 | fn len(&self) -> usize { loop {} } | 785 | fn len(&self) -> usize { loop {} } |
796 | } | 786 | } |
797 | fn test() { | 787 | fn test() { |
798 | let a = [1, 2, 3]; | 788 | let a = [1, 2, 3]; |
799 | a.len()<|>; | 789 | a.len(); |
800 | } | 790 | } //^ usize |
801 | "#, | 791 | "#, |
802 | ); | 792 | ); |
803 | assert_eq!(t, "usize"); | ||
804 | } | 793 | } |
805 | 794 | ||
806 | #[test] | 795 | #[test] |
807 | fn method_resolution_trait_from_prelude() { | 796 | fn method_resolution_trait_from_prelude() { |
808 | let (db, pos) = TestDB::with_position( | 797 | check_types( |
809 | r#" | 798 | r#" |
810 | //- /main.rs crate:main deps:other_crate | 799 | //- /main.rs crate:main deps:other_crate |
811 | struct S; | 800 | struct S; |
812 | impl Clone for S {} | 801 | impl Clone for S {} |
813 | 802 | ||
814 | fn test() { | 803 | fn test() { |
815 | S.clone()<|>; | 804 | S.clone(); |
805 | //^ S | ||
816 | } | 806 | } |
817 | 807 | ||
818 | //- /lib.rs crate:other_crate | 808 | //- /lib.rs crate:other_crate |
@@ -825,115 +815,107 @@ mod foo { | |||
825 | } | 815 | } |
826 | "#, | 816 | "#, |
827 | ); | 817 | ); |
828 | assert_eq!("S", type_at_pos(&db, pos)); | ||
829 | } | 818 | } |
830 | 819 | ||
831 | #[test] | 820 | #[test] |
832 | fn method_resolution_where_clause_for_unknown_trait() { | 821 | fn method_resolution_where_clause_for_unknown_trait() { |
833 | // The blanket impl currently applies because we ignore the unresolved where clause | 822 | // The blanket impl currently applies because we ignore the unresolved where clause |
834 | let t = type_at( | 823 | check_types( |
835 | r#" | 824 | r#" |
836 | //- /main.rs | ||
837 | trait Trait { fn foo(self) -> u128; } | 825 | trait Trait { fn foo(self) -> u128; } |
838 | struct S; | 826 | struct S; |
839 | impl<T> Trait for T where T: UnknownTrait {} | 827 | impl<T> Trait for T where T: UnknownTrait {} |
840 | fn test() { (&S).foo()<|>; } | 828 | fn test() { (&S).foo(); } |
829 | //^ u128 | ||
841 | "#, | 830 | "#, |
842 | ); | 831 | ); |
843 | assert_eq!(t, "u128"); | ||
844 | } | 832 | } |
845 | 833 | ||
846 | #[test] | 834 | #[test] |
847 | fn method_resolution_where_clause_not_met() { | 835 | fn method_resolution_where_clause_not_met() { |
848 | // The blanket impl shouldn't apply because we can't prove S: Clone | 836 | // The blanket impl shouldn't apply because we can't prove S: Clone |
849 | let t = type_at( | 837 | // This is also to make sure that we don't resolve to the foo method just |
838 | // because that's the only method named foo we can find, which would make | ||
839 | // the below tests not work | ||
840 | check_types( | ||
850 | r#" | 841 | r#" |
851 | //- /main.rs | ||
852 | trait Clone {} | 842 | trait Clone {} |
853 | trait Trait { fn foo(self) -> u128; } | 843 | trait Trait { fn foo(self) -> u128; } |
854 | struct S; | 844 | struct S; |
855 | impl<T> Trait for T where T: Clone {} | 845 | impl<T> Trait for T where T: Clone {} |
856 | fn test() { (&S).foo()<|>; } | 846 | fn test() { (&S).foo(); } |
847 | //^ {unknown} | ||
857 | "#, | 848 | "#, |
858 | ); | 849 | ); |
859 | // This is also to make sure that we don't resolve to the foo method just | ||
860 | // because that's the only method named foo we can find, which would make | ||
861 | // the below tests not work | ||
862 | assert_eq!(t, "{unknown}"); | ||
863 | } | 850 | } |
864 | 851 | ||
865 | #[test] | 852 | #[test] |
866 | fn method_resolution_where_clause_inline_not_met() { | 853 | fn method_resolution_where_clause_inline_not_met() { |
867 | // The blanket impl shouldn't apply because we can't prove S: Clone | 854 | // The blanket impl shouldn't apply because we can't prove S: Clone |
868 | let t = type_at( | 855 | check_types( |
869 | r#" | 856 | r#" |
870 | //- /main.rs | ||
871 | trait Clone {} | 857 | trait Clone {} |
872 | trait Trait { fn foo(self) -> u128; } | 858 | trait Trait { fn foo(self) -> u128; } |
873 | struct S; | 859 | struct S; |
874 | impl<T: Clone> Trait for T {} | 860 | impl<T: Clone> Trait for T {} |
875 | fn test() { (&S).foo()<|>; } | 861 | fn test() { (&S).foo(); } |
862 | //^ {unknown} | ||
876 | "#, | 863 | "#, |
877 | ); | 864 | ); |
878 | assert_eq!(t, "{unknown}"); | ||
879 | } | 865 | } |
880 | 866 | ||
881 | #[test] | 867 | #[test] |
882 | fn method_resolution_where_clause_1() { | 868 | fn method_resolution_where_clause_1() { |
883 | let t = type_at( | 869 | check_types( |
884 | r#" | 870 | r#" |
885 | //- /main.rs | ||
886 | trait Clone {} | 871 | trait Clone {} |
887 | trait Trait { fn foo(self) -> u128; } | 872 | trait Trait { fn foo(self) -> u128; } |
888 | struct S; | 873 | struct S; |
889 | impl Clone for S {} | 874 | impl Clone for S {} |
890 | impl<T> Trait for T where T: Clone {} | 875 | impl<T> Trait for T where T: Clone {} |
891 | fn test() { S.foo()<|>; } | 876 | fn test() { S.foo(); } |
877 | //^ u128 | ||
892 | "#, | 878 | "#, |
893 | ); | 879 | ); |
894 | assert_eq!(t, "u128"); | ||
895 | } | 880 | } |
896 | 881 | ||
897 | #[test] | 882 | #[test] |
898 | fn method_resolution_where_clause_2() { | 883 | fn method_resolution_where_clause_2() { |
899 | let t = type_at( | 884 | check_types( |
900 | r#" | 885 | r#" |
901 | //- /main.rs | ||
902 | trait Into<T> { fn into(self) -> T; } | 886 | trait Into<T> { fn into(self) -> T; } |
903 | trait From<T> { fn from(other: T) -> Self; } | 887 | trait From<T> { fn from(other: T) -> Self; } |
904 | struct S1; | 888 | struct S1; |
905 | struct S2; | 889 | struct S2; |
906 | impl From<S2> for S1 {} | 890 | impl From<S2> for S1 {} |
907 | impl<T, U> Into<U> for T where U: From<T> {} | 891 | impl<T, U> Into<U> for T where U: From<T> {} |
908 | fn test() { S2.into()<|>; } | 892 | fn test() { S2.into(); } |
893 | //^ {unknown} | ||
909 | "#, | 894 | "#, |
910 | ); | 895 | ); |
911 | assert_eq!(t, "{unknown}"); | ||
912 | } | 896 | } |
913 | 897 | ||
914 | #[test] | 898 | #[test] |
915 | fn method_resolution_where_clause_inline() { | 899 | fn method_resolution_where_clause_inline() { |
916 | let t = type_at( | 900 | check_types( |
917 | r#" | 901 | r#" |
918 | //- /main.rs | ||
919 | trait Into<T> { fn into(self) -> T; } | 902 | trait Into<T> { fn into(self) -> T; } |
920 | trait From<T> { fn from(other: T) -> Self; } | 903 | trait From<T> { fn from(other: T) -> Self; } |
921 | struct S1; | 904 | struct S1; |
922 | struct S2; | 905 | struct S2; |
923 | impl From<S2> for S1 {} | 906 | impl From<S2> for S1 {} |
924 | impl<T, U: From<T>> Into<U> for T {} | 907 | impl<T, U: From<T>> Into<U> for T {} |
925 | fn test() { S2.into()<|>; } | 908 | fn test() { S2.into(); } |
909 | //^ {unknown} | ||
926 | "#, | 910 | "#, |
927 | ); | 911 | ); |
928 | assert_eq!(t, "{unknown}"); | ||
929 | } | 912 | } |
930 | 913 | ||
931 | #[test] | 914 | #[test] |
932 | fn method_resolution_overloaded_method() { | 915 | fn method_resolution_overloaded_method() { |
933 | test_utils::mark::check!(impl_self_type_match_without_receiver); | 916 | test_utils::mark::check!(impl_self_type_match_without_receiver); |
934 | let t = type_at( | 917 | check_types( |
935 | r#" | 918 | r#" |
936 | //- /main.rs | ||
937 | struct Wrapper<T>(T); | 919 | struct Wrapper<T>(T); |
938 | struct Foo<T>(T); | 920 | struct Foo<T>(T); |
939 | struct Bar<T>(T); | 921 | struct Bar<T>(T); |
@@ -953,30 +935,30 @@ impl<T> Wrapper<Bar<T>> { | |||
953 | fn main() { | 935 | fn main() { |
954 | let a = Wrapper::<Foo<f32>>::new(1.0); | 936 | let a = Wrapper::<Foo<f32>>::new(1.0); |
955 | let b = Wrapper::<Bar<f32>>::new(1.0); | 937 | let b = Wrapper::<Bar<f32>>::new(1.0); |
956 | (a, b)<|>; | 938 | (a, b); |
939 | //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) | ||
957 | } | 940 | } |
958 | "#, | 941 | "#, |
959 | ); | 942 | ); |
960 | assert_eq!(t, "(Wrapper<Foo<f32>>, Wrapper<Bar<f32>>)") | ||
961 | } | 943 | } |
962 | 944 | ||
963 | #[test] | 945 | #[test] |
964 | fn method_resolution_encountering_fn_type() { | 946 | fn method_resolution_encountering_fn_type() { |
965 | type_at( | 947 | check_types( |
966 | r#" | 948 | r#" |
967 | //- /main.rs | 949 | //- /main.rs |
968 | fn foo() {} | 950 | fn foo() {} |
969 | trait FnOnce { fn call(self); } | 951 | trait FnOnce { fn call(self); } |
970 | fn test() { foo.call()<|>; } | 952 | fn test() { foo.call(); } |
953 | //^ {unknown} | ||
971 | "#, | 954 | "#, |
972 | ); | 955 | ); |
973 | } | 956 | } |
974 | 957 | ||
975 | #[test] | 958 | #[test] |
976 | fn method_resolution_non_parameter_type() { | 959 | fn method_resolution_non_parameter_type() { |
977 | let t = type_at( | 960 | check_types( |
978 | r#" | 961 | r#" |
979 | //- /main.rs | ||
980 | mod a { | 962 | mod a { |
981 | pub trait Foo { | 963 | pub trait Foo { |
982 | fn foo(&self); | 964 | fn foo(&self); |
@@ -988,18 +970,16 @@ fn foo<T>(t: Wrapper<T>) | |||
988 | where | 970 | where |
989 | Wrapper<T>: a::Foo, | 971 | Wrapper<T>: a::Foo, |
990 | { | 972 | { |
991 | t.foo()<|>; | 973 | t.foo(); |
992 | } | 974 | } //^ {unknown} |
993 | "#, | 975 | "#, |
994 | ); | 976 | ); |
995 | assert_eq!(t, "{unknown}"); | ||
996 | } | 977 | } |
997 | 978 | ||
998 | #[test] | 979 | #[test] |
999 | fn method_resolution_3373() { | 980 | fn method_resolution_3373() { |
1000 | let t = type_at( | 981 | check_types( |
1001 | r#" | 982 | r#" |
1002 | //- /main.rs | ||
1003 | struct A<T>(T); | 983 | struct A<T>(T); |
1004 | 984 | ||
1005 | impl A<i32> { | 985 | impl A<i32> { |
@@ -1007,19 +987,17 @@ impl A<i32> { | |||
1007 | } | 987 | } |
1008 | 988 | ||
1009 | fn main() { | 989 | fn main() { |
1010 | A::from(3)<|>; | 990 | A::from(3); |
1011 | } | 991 | } //^ A<i32> |
1012 | "#, | 992 | "#, |
1013 | ); | 993 | ); |
1014 | assert_eq!(t, "A<i32>"); | ||
1015 | } | 994 | } |
1016 | 995 | ||
1017 | #[test] | 996 | #[test] |
1018 | fn method_resolution_slow() { | 997 | fn method_resolution_slow() { |
1019 | // this can get quite slow if we set the solver size limit too high | 998 | // this can get quite slow if we set the solver size limit too high |
1020 | let t = type_at( | 999 | check_types( |
1021 | r#" | 1000 | r#" |
1022 | //- /main.rs | ||
1023 | trait SendX {} | 1001 | trait SendX {} |
1024 | 1002 | ||
1025 | struct S1; impl SendX for S1 {} | 1003 | struct S1; impl SendX for S1 {} |
@@ -1037,10 +1015,10 @@ trait FnX {} | |||
1037 | 1015 | ||
1038 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | 1016 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} |
1039 | 1017 | ||
1040 | fn test() { (S {}).method()<|>; } | 1018 | fn test() { (S {}).method(); } |
1019 | //^ () | ||
1041 | "#, | 1020 | "#, |
1042 | ); | 1021 | ); |
1043 | assert_eq!(t, "()"); | ||
1044 | } | 1022 | } |
1045 | 1023 | ||
1046 | #[test] | 1024 | #[test] |