aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/_match.rs857
-rw-r--r--crates/ra_hir_ty/src/db.rs15
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs12
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs81
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs2
-rw-r--r--crates/ra_hir_ty/src/lib.rs63
-rw-r--r--crates/ra_hir_ty/src/lower.rs25
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs69
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs151
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs223
-rw-r--r--crates/ra_hir_ty/src/traits.rs43
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs20
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs28
-rw-r--r--crates/ra_hir_ty/src/utils.rs14
14 files changed, 1090 insertions, 513 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index fff257193..5495ce284 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -312,20 +312,16 @@ impl PatStack {
312 Self(v) 312 Self(v)
313 } 313 }
314 314
315 fn is_empty(&self) -> bool {
316 self.0.is_empty()
317 }
318
319 fn head(&self) -> PatIdOrWild {
320 self.0[0]
321 }
322
323 fn get_head(&self) -> Option<PatIdOrWild> { 315 fn get_head(&self) -> Option<PatIdOrWild> {
324 self.0.first().copied() 316 self.0.first().copied()
325 } 317 }
326 318
319 fn tail(&self) -> &[PatIdOrWild] {
320 self.0.get(1..).unwrap_or(&[])
321 }
322
327 fn to_tail(&self) -> PatStack { 323 fn to_tail(&self) -> PatStack {
328 Self::from_slice(&self.0[1..]) 324 Self::from_slice(self.tail())
329 } 325 }
330 326
331 fn replace_head_with<I, T>(&self, pats: I) -> PatStack 327 fn replace_head_with<I, T>(&self, pats: I) -> PatStack
@@ -347,7 +343,7 @@ impl PatStack {
347 /// 343 ///
348 /// See the module docs and the associated documentation in rustc for details. 344 /// See the module docs and the associated documentation in rustc for details.
349 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> { 345 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> {
350 if matches!(self.head().as_pat(cx), Pat::Wild) { 346 if matches!(self.get_head()?.as_pat(cx), Pat::Wild) {
351 Some(self.to_tail()) 347 Some(self.to_tail())
352 } else { 348 } else {
353 None 349 None
@@ -362,7 +358,13 @@ impl PatStack {
362 cx: &MatchCheckCtx, 358 cx: &MatchCheckCtx,
363 constructor: &Constructor, 359 constructor: &Constructor,
364 ) -> MatchCheckResult<Option<PatStack>> { 360 ) -> MatchCheckResult<Option<PatStack>> {
365 let result = match (self.head().as_pat(cx), constructor) { 361 let head = match self.get_head() {
362 Some(head) => head,
363 None => return Ok(None),
364 };
365
366 let head_pat = head.as_pat(cx);
367 let result = match (head_pat, constructor) {
366 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => { 368 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => {
367 if ellipsis.is_some() { 369 if ellipsis.is_some() {
368 // If there are ellipsis here, we should add the correct number of 370 // If there are ellipsis here, we should add the correct number of
@@ -389,7 +391,7 @@ impl PatStack {
389 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?), 391 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?),
390 (Pat::Path(_), Constructor::Enum(constructor)) => { 392 (Pat::Path(_), Constructor::Enum(constructor)) => {
391 // unit enum variants become `Pat::Path` 393 // unit enum variants become `Pat::Path`
392 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 394 let pat_id = head.as_id().expect("we know this isn't a wild");
393 if !enum_variant_matches(cx, pat_id, *constructor) { 395 if !enum_variant_matches(cx, pat_id, *constructor) {
394 None 396 None
395 } else { 397 } else {
@@ -400,7 +402,7 @@ impl PatStack {
400 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. }, 402 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. },
401 Constructor::Enum(enum_constructor), 403 Constructor::Enum(enum_constructor),
402 ) => { 404 ) => {
403 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 405 let pat_id = head.as_id().expect("we know this isn't a wild");
404 if !enum_variant_matches(cx, pat_id, *enum_constructor) { 406 if !enum_variant_matches(cx, pat_id, *enum_constructor) {
405 None 407 None
406 } else { 408 } else {
@@ -440,7 +442,7 @@ impl PatStack {
440 } 442 }
441 } 443 }
442 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => { 444 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => {
443 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 445 let pat_id = head.as_id().expect("we know this isn't a wild");
444 if !enum_variant_matches(cx, pat_id, *e) { 446 if !enum_variant_matches(cx, pat_id, *e) {
445 None 447 None
446 } else { 448 } else {
@@ -486,7 +488,7 @@ impl PatStack {
486 ) -> MatchCheckResult<PatStack> { 488 ) -> MatchCheckResult<PatStack> {
487 assert_eq!( 489 assert_eq!(
488 Pat::Wild, 490 Pat::Wild,
489 self.head().as_pat(cx), 491 self.get_head().expect("expand_wildcard called on empty PatStack").as_pat(cx),
490 "expand_wildcard must only be called on PatStack with wild at head", 492 "expand_wildcard must only be called on PatStack with wild at head",
491 ); 493 );
492 494
@@ -504,7 +506,6 @@ impl PatStack {
504 } 506 }
505} 507}
506 508
507#[derive(Debug)]
508/// A collection of PatStack. 509/// A collection of PatStack.
509/// 510///
510/// This type is modeled from the struct of the same name in `rustc`. 511/// This type is modeled from the struct of the same name in `rustc`.
@@ -531,7 +532,7 @@ impl Matrix {
531 } 532 }
532 533
533 fn heads(&self) -> Vec<PatIdOrWild> { 534 fn heads(&self) -> Vec<PatIdOrWild> {
534 self.0.iter().map(|p| p.head()).collect() 535 self.0.iter().flat_map(|p| p.get_head()).collect()
535 } 536 }
536 537
537 /// Computes `D(self)` for each contained PatStack. 538 /// Computes `D(self)` for each contained PatStack.
@@ -618,13 +619,16 @@ pub(crate) fn is_useful(
618 _ => (), 619 _ => (),
619 } 620 }
620 621
621 if v.is_empty() { 622 let head = match v.get_head() {
622 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful }; 623 Some(head) => head,
624 None => {
625 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
623 626
624 return Ok(result); 627 return Ok(result);
625 } 628 }
629 };
626 630
627 if let Pat::Or(pat_ids) = v.head().as_pat(cx) { 631 if let Pat::Or(pat_ids) = head.as_pat(cx) {
628 let mut found_unimplemented = false; 632 let mut found_unimplemented = false;
629 let any_useful = pat_ids.iter().any(|&pat_id| { 633 let any_useful = pat_ids.iter().any(|&pat_id| {
630 let v = PatStack::from_pattern(pat_id); 634 let v = PatStack::from_pattern(pat_id);
@@ -648,7 +652,7 @@ pub(crate) fn is_useful(
648 }; 652 };
649 } 653 }
650 654
651 if let Some(constructor) = pat_constructor(cx, v.head())? { 655 if let Some(constructor) = pat_constructor(cx, head)? {
652 let matrix = matrix.specialize_constructor(&cx, &constructor)?; 656 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
653 let v = v 657 let v = v
654 .specialize_constructor(&cx, &constructor)? 658 .specialize_constructor(&cx, &constructor)?
@@ -837,194 +841,193 @@ mod tests {
837 841
838 pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB}; 842 pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB};
839 843
840 pub(super) fn check_diagnostic_message(content: &str) -> String { 844 pub(super) fn check_diagnostic_message(ra_fixture: &str) -> String {
841 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().0 845 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().0
842 } 846 }
843 847
844 pub(super) fn check_diagnostic(content: &str) { 848 pub(super) fn check_diagnostic(ra_fixture: &str) {
845 let diagnostic_count = 849 let diagnostic_count =
846 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; 850 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1;
847 851
848 assert_eq!(1, diagnostic_count, "no diagnostic reported"); 852 assert_eq!(1, diagnostic_count, "no diagnostic reported");
849 } 853 }
850 854
851 pub(super) fn check_no_diagnostic(content: &str) { 855 pub(super) fn check_no_diagnostic(ra_fixture: &str) {
852 let diagnostic_count = 856 let (s, diagnostic_count) =
853 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; 857 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>();
854 858
855 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); 859 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s);
856 } 860 }
857 861
858 #[test] 862 #[test]
859 fn empty_tuple_no_arms_diagnostic_message() { 863 fn empty_tuple_no_arms_diagnostic_message() {
860 let content = r"
861 fn test_fn() {
862 match () {
863 }
864 }
865 ";
866
867 assert_snapshot!( 864 assert_snapshot!(
868 check_diagnostic_message(content), 865 check_diagnostic_message(r"
866 fn test_fn() {
867 match () {
868 }
869 }
870 "),
869 @"\"()\": Missing match arm\n" 871 @"\"()\": Missing match arm\n"
870 ); 872 );
871 } 873 }
872 874
873 #[test] 875 #[test]
874 fn empty_tuple_no_arms() { 876 fn empty_tuple_no_arms() {
875 let content = r" 877 check_diagnostic(
878 r"
876 fn test_fn() { 879 fn test_fn() {
877 match () { 880 match () {
878 } 881 }
879 } 882 }
880 "; 883 ",
881 884 );
882 check_diagnostic(content);
883 } 885 }
884 886
885 #[test] 887 #[test]
886 fn empty_tuple_wild() { 888 fn empty_tuple_wild() {
887 let content = r" 889 check_no_diagnostic(
890 r"
888 fn test_fn() { 891 fn test_fn() {
889 match () { 892 match () {
890 _ => {} 893 _ => {}
891 } 894 }
892 } 895 }
893 "; 896 ",
894 897 );
895 check_no_diagnostic(content);
896 } 898 }
897 899
898 #[test] 900 #[test]
899 fn empty_tuple_no_diagnostic() { 901 fn empty_tuple_no_diagnostic() {
900 let content = r" 902 check_no_diagnostic(
903 r"
901 fn test_fn() { 904 fn test_fn() {
902 match () { 905 match () {
903 () => {} 906 () => {}
904 } 907 }
905 } 908 }
906 "; 909 ",
907 910 );
908 check_no_diagnostic(content);
909 } 911 }
910 912
911 #[test] 913 #[test]
912 fn tuple_of_empty_tuple_no_arms() { 914 fn tuple_of_empty_tuple_no_arms() {
913 let content = r" 915 check_diagnostic(
916 r"
914 fn test_fn() { 917 fn test_fn() {
915 match (()) { 918 match (()) {
916 } 919 }
917 } 920 }
918 "; 921 ",
919 922 );
920 check_diagnostic(content);
921 } 923 }
922 924
923 #[test] 925 #[test]
924 fn tuple_of_empty_tuple_no_diagnostic() { 926 fn tuple_of_empty_tuple_no_diagnostic() {
925 let content = r" 927 check_no_diagnostic(
928 r"
926 fn test_fn() { 929 fn test_fn() {
927 match (()) { 930 match (()) {
928 (()) => {} 931 (()) => {}
929 } 932 }
930 } 933 }
931 "; 934 ",
932 935 );
933 check_no_diagnostic(content);
934 } 936 }
935 937
936 #[test] 938 #[test]
937 fn tuple_of_two_empty_tuple_no_arms() { 939 fn tuple_of_two_empty_tuple_no_arms() {
938 let content = r" 940 check_diagnostic(
941 r"
939 fn test_fn() { 942 fn test_fn() {
940 match ((), ()) { 943 match ((), ()) {
941 } 944 }
942 } 945 }
943 "; 946 ",
944 947 );
945 check_diagnostic(content);
946 } 948 }
947 949
948 #[test] 950 #[test]
949 fn tuple_of_two_empty_tuple_no_diagnostic() { 951 fn tuple_of_two_empty_tuple_no_diagnostic() {
950 let content = r" 952 check_no_diagnostic(
953 r"
951 fn test_fn() { 954 fn test_fn() {
952 match ((), ()) { 955 match ((), ()) {
953 ((), ()) => {} 956 ((), ()) => {}
954 } 957 }
955 } 958 }
956 "; 959 ",
957 960 );
958 check_no_diagnostic(content);
959 } 961 }
960 962
961 #[test] 963 #[test]
962 fn bool_no_arms() { 964 fn bool_no_arms() {
963 let content = r" 965 check_diagnostic(
966 r"
964 fn test_fn() { 967 fn test_fn() {
965 match false { 968 match false {
966 } 969 }
967 } 970 }
968 "; 971 ",
969 972 );
970 check_diagnostic(content);
971 } 973 }
972 974
973 #[test] 975 #[test]
974 fn bool_missing_arm() { 976 fn bool_missing_arm() {
975 let content = r" 977 check_diagnostic(
978 r"
976 fn test_fn() { 979 fn test_fn() {
977 match false { 980 match false {
978 true => {} 981 true => {}
979 } 982 }
980 } 983 }
981 "; 984 ",
982 985 );
983 check_diagnostic(content);
984 } 986 }
985 987
986 #[test] 988 #[test]
987 fn bool_no_diagnostic() { 989 fn bool_no_diagnostic() {
988 let content = r" 990 check_no_diagnostic(
991 r"
989 fn test_fn() { 992 fn test_fn() {
990 match false { 993 match false {
991 true => {} 994 true => {}
992 false => {} 995 false => {}
993 } 996 }
994 } 997 }
995 "; 998 ",
996 999 );
997 check_no_diagnostic(content);
998 } 1000 }
999 1001
1000 #[test] 1002 #[test]
1001 fn tuple_of_bools_no_arms() { 1003 fn tuple_of_bools_no_arms() {
1002 let content = r" 1004 check_diagnostic(
1005 r"
1003 fn test_fn() { 1006 fn test_fn() {
1004 match (false, true) { 1007 match (false, true) {
1005 } 1008 }
1006 } 1009 }
1007 "; 1010 ",
1008 1011 );
1009 check_diagnostic(content);
1010 } 1012 }
1011 1013
1012 #[test] 1014 #[test]
1013 fn tuple_of_bools_missing_arms() { 1015 fn tuple_of_bools_missing_arms() {
1014 let content = r" 1016 check_diagnostic(
1017 r"
1015 fn test_fn() { 1018 fn test_fn() {
1016 match (false, true) { 1019 match (false, true) {
1017 (true, true) => {}, 1020 (true, true) => {},
1018 } 1021 }
1019 } 1022 }
1020 "; 1023 ",
1021 1024 );
1022 check_diagnostic(content);
1023 } 1025 }
1024 1026
1025 #[test] 1027 #[test]
1026 fn tuple_of_bools_missing_arm() { 1028 fn tuple_of_bools_missing_arm() {
1027 let content = r" 1029 check_diagnostic(
1030 r"
1028 fn test_fn() { 1031 fn test_fn() {
1029 match (false, true) { 1032 match (false, true) {
1030 (false, true) => {}, 1033 (false, true) => {},
@@ -1032,14 +1035,14 @@ mod tests {
1032 (true, false) => {}, 1035 (true, false) => {},
1033 } 1036 }
1034 } 1037 }
1035 "; 1038 ",
1036 1039 );
1037 check_diagnostic(content);
1038 } 1040 }
1039 1041
1040 #[test] 1042 #[test]
1041 fn tuple_of_bools_with_wilds() { 1043 fn tuple_of_bools_with_wilds() {
1042 let content = r" 1044 check_no_diagnostic(
1045 r"
1043 fn test_fn() { 1046 fn test_fn() {
1044 match (false, true) { 1047 match (false, true) {
1045 (false, _) => {}, 1048 (false, _) => {},
@@ -1047,14 +1050,14 @@ mod tests {
1047 (_, true) => {}, 1050 (_, true) => {},
1048 } 1051 }
1049 } 1052 }
1050 "; 1053 ",
1051 1054 );
1052 check_no_diagnostic(content);
1053 } 1055 }
1054 1056
1055 #[test] 1057 #[test]
1056 fn tuple_of_bools_no_diagnostic() { 1058 fn tuple_of_bools_no_diagnostic() {
1057 let content = r" 1059 check_no_diagnostic(
1060 r"
1058 fn test_fn() { 1061 fn test_fn() {
1059 match (false, true) { 1062 match (false, true) {
1060 (true, true) => {}, 1063 (true, true) => {},
@@ -1063,27 +1066,27 @@ mod tests {
1063 (false, false) => {}, 1066 (false, false) => {},
1064 } 1067 }
1065 } 1068 }
1066 "; 1069 ",
1067 1070 );
1068 check_no_diagnostic(content);
1069 } 1071 }
1070 1072
1071 #[test] 1073 #[test]
1072 fn tuple_of_bools_binding_missing_arms() { 1074 fn tuple_of_bools_binding_missing_arms() {
1073 let content = r" 1075 check_diagnostic(
1076 r"
1074 fn test_fn() { 1077 fn test_fn() {
1075 match (false, true) { 1078 match (false, true) {
1076 (true, _x) => {}, 1079 (true, _x) => {},
1077 } 1080 }
1078 } 1081 }
1079 "; 1082 ",
1080 1083 );
1081 check_diagnostic(content);
1082 } 1084 }
1083 1085
1084 #[test] 1086 #[test]
1085 fn tuple_of_bools_binding_no_diagnostic() { 1087 fn tuple_of_bools_binding_no_diagnostic() {
1086 let content = r" 1088 check_no_diagnostic(
1089 r"
1087 fn test_fn() { 1090 fn test_fn() {
1088 match (false, true) { 1091 match (false, true) {
1089 (true, _x) => {}, 1092 (true, _x) => {},
@@ -1091,80 +1094,80 @@ mod tests {
1091 (false, false) => {}, 1094 (false, false) => {},
1092 } 1095 }
1093 } 1096 }
1094 "; 1097 ",
1095 1098 );
1096 check_no_diagnostic(content);
1097 } 1099 }
1098 1100
1099 #[test] 1101 #[test]
1100 fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() { 1102 fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() {
1101 let content = r" 1103 check_no_diagnostic(
1104 r"
1102 fn test_fn() { 1105 fn test_fn() {
1103 match (false, true, false) { 1106 match (false, true, false) {
1104 (false, ..) => {}, 1107 (false, ..) => {},
1105 (true, ..) => {}, 1108 (true, ..) => {},
1106 } 1109 }
1107 } 1110 }
1108 "; 1111 ",
1109 1112 );
1110 check_no_diagnostic(content);
1111 } 1113 }
1112 1114
1113 #[test] 1115 #[test]
1114 fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() { 1116 fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() {
1115 let content = r" 1117 check_no_diagnostic(
1118 r"
1116 fn test_fn() { 1119 fn test_fn() {
1117 match (false, true, false) { 1120 match (false, true, false) {
1118 (.., false) => {}, 1121 (.., false) => {},
1119 (.., true) => {}, 1122 (.., true) => {},
1120 } 1123 }
1121 } 1124 }
1122 "; 1125 ",
1123 1126 );
1124 check_no_diagnostic(content);
1125 } 1127 }
1126 1128
1127 #[test] 1129 #[test]
1128 fn tuple_of_bools_with_ellipsis_no_diagnostic() { 1130 fn tuple_of_bools_with_ellipsis_no_diagnostic() {
1129 let content = r" 1131 check_no_diagnostic(
1132 r"
1130 fn test_fn() { 1133 fn test_fn() {
1131 match (false, true, false) { 1134 match (false, true, false) {
1132 (..) => {}, 1135 (..) => {},
1133 } 1136 }
1134 } 1137 }
1135 "; 1138 ",
1136 1139 );
1137 check_no_diagnostic(content);
1138 } 1140 }
1139 1141
1140 #[test] 1142 #[test]
1141 fn tuple_of_tuple_and_bools_no_arms() { 1143 fn tuple_of_tuple_and_bools_no_arms() {
1142 let content = r" 1144 check_diagnostic(
1145 r"
1143 fn test_fn() { 1146 fn test_fn() {
1144 match (false, ((), false)) { 1147 match (false, ((), false)) {
1145 } 1148 }
1146 } 1149 }
1147 "; 1150 ",
1148 1151 );
1149 check_diagnostic(content);
1150 } 1152 }
1151 1153
1152 #[test] 1154 #[test]
1153 fn tuple_of_tuple_and_bools_missing_arms() { 1155 fn tuple_of_tuple_and_bools_missing_arms() {
1154 let content = r" 1156 check_diagnostic(
1157 r"
1155 fn test_fn() { 1158 fn test_fn() {
1156 match (false, ((), false)) { 1159 match (false, ((), false)) {
1157 (true, ((), true)) => {}, 1160 (true, ((), true)) => {},
1158 } 1161 }
1159 } 1162 }
1160 "; 1163 ",
1161 1164 );
1162 check_diagnostic(content);
1163 } 1165 }
1164 1166
1165 #[test] 1167 #[test]
1166 fn tuple_of_tuple_and_bools_no_diagnostic() { 1168 fn tuple_of_tuple_and_bools_no_diagnostic() {
1167 let content = r" 1169 check_no_diagnostic(
1170 r"
1168 fn test_fn() { 1171 fn test_fn() {
1169 match (false, ((), false)) { 1172 match (false, ((), false)) {
1170 (true, ((), true)) => {}, 1173 (true, ((), true)) => {},
@@ -1173,27 +1176,27 @@ mod tests {
1173 (false, ((), false)) => {}, 1176 (false, ((), false)) => {},
1174 } 1177 }
1175 } 1178 }
1176 "; 1179 ",
1177 1180 );
1178 check_no_diagnostic(content);
1179 } 1181 }
1180 1182
1181 #[test] 1183 #[test]
1182 fn tuple_of_tuple_and_bools_wildcard_missing_arms() { 1184 fn tuple_of_tuple_and_bools_wildcard_missing_arms() {
1183 let content = r" 1185 check_diagnostic(
1186 r"
1184 fn test_fn() { 1187 fn test_fn() {
1185 match (false, ((), false)) { 1188 match (false, ((), false)) {
1186 (true, _) => {}, 1189 (true, _) => {},
1187 } 1190 }
1188 } 1191 }
1189 "; 1192 ",
1190 1193 );
1191 check_diagnostic(content);
1192 } 1194 }
1193 1195
1194 #[test] 1196 #[test]
1195 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() { 1197 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() {
1196 let content = r" 1198 check_no_diagnostic(
1199 r"
1197 fn test_fn() { 1200 fn test_fn() {
1198 match (false, ((), false)) { 1201 match (false, ((), false)) {
1199 (true, ((), true)) => {}, 1202 (true, ((), true)) => {},
@@ -1201,14 +1204,14 @@ mod tests {
1201 (false, _) => {}, 1204 (false, _) => {},
1202 } 1205 }
1203 } 1206 }
1204 "; 1207 ",
1205 1208 );
1206 check_no_diagnostic(content);
1207 } 1209 }
1208 1210
1209 #[test] 1211 #[test]
1210 fn enum_no_arms() { 1212 fn enum_no_arms() {
1211 let content = r" 1213 check_diagnostic(
1214 r"
1212 enum Either { 1215 enum Either {
1213 A, 1216 A,
1214 B, 1217 B,
@@ -1217,14 +1220,14 @@ mod tests {
1217 match Either::A { 1220 match Either::A {
1218 } 1221 }
1219 } 1222 }
1220 "; 1223 ",
1221 1224 );
1222 check_diagnostic(content);
1223 } 1225 }
1224 1226
1225 #[test] 1227 #[test]
1226 fn enum_missing_arms() { 1228 fn enum_missing_arms() {
1227 let content = r" 1229 check_diagnostic(
1230 r"
1228 enum Either { 1231 enum Either {
1229 A, 1232 A,
1230 B, 1233 B,
@@ -1234,14 +1237,14 @@ mod tests {
1234 Either::A => {}, 1237 Either::A => {},
1235 } 1238 }
1236 } 1239 }
1237 "; 1240 ",
1238 1241 );
1239 check_diagnostic(content);
1240 } 1242 }
1241 1243
1242 #[test] 1244 #[test]
1243 fn enum_no_diagnostic() { 1245 fn enum_no_diagnostic() {
1244 let content = r" 1246 check_no_diagnostic(
1247 r"
1245 enum Either { 1248 enum Either {
1246 A, 1249 A,
1247 B, 1250 B,
@@ -1252,14 +1255,14 @@ mod tests {
1252 Either::B => {}, 1255 Either::B => {},
1253 } 1256 }
1254 } 1257 }
1255 "; 1258 ",
1256 1259 );
1257 check_no_diagnostic(content);
1258 } 1260 }
1259 1261
1260 #[test] 1262 #[test]
1261 fn enum_ref_missing_arms() { 1263 fn enum_ref_missing_arms() {
1262 let content = r" 1264 check_diagnostic(
1265 r"
1263 enum Either { 1266 enum Either {
1264 A, 1267 A,
1265 B, 1268 B,
@@ -1269,14 +1272,14 @@ mod tests {
1269 Either::A => {}, 1272 Either::A => {},
1270 } 1273 }
1271 } 1274 }
1272 "; 1275 ",
1273 1276 );
1274 check_diagnostic(content);
1275 } 1277 }
1276 1278
1277 #[test] 1279 #[test]
1278 fn enum_ref_no_diagnostic() { 1280 fn enum_ref_no_diagnostic() {
1279 let content = r" 1281 check_no_diagnostic(
1282 r"
1280 enum Either { 1283 enum Either {
1281 A, 1284 A,
1282 B, 1285 B,
@@ -1287,14 +1290,14 @@ mod tests {
1287 Either::B => {}, 1290 Either::B => {},
1288 } 1291 }
1289 } 1292 }
1290 "; 1293 ",
1291 1294 );
1292 check_no_diagnostic(content);
1293 } 1295 }
1294 1296
1295 #[test] 1297 #[test]
1296 fn enum_containing_bool_no_arms() { 1298 fn enum_containing_bool_no_arms() {
1297 let content = r" 1299 check_diagnostic(
1300 r"
1298 enum Either { 1301 enum Either {
1299 A(bool), 1302 A(bool),
1300 B, 1303 B,
@@ -1303,14 +1306,14 @@ mod tests {
1303 match Either::B { 1306 match Either::B {
1304 } 1307 }
1305 } 1308 }
1306 "; 1309 ",
1307 1310 );
1308 check_diagnostic(content);
1309 } 1311 }
1310 1312
1311 #[test] 1313 #[test]
1312 fn enum_containing_bool_missing_arms() { 1314 fn enum_containing_bool_missing_arms() {
1313 let content = r" 1315 check_diagnostic(
1316 r"
1314 enum Either { 1317 enum Either {
1315 A(bool), 1318 A(bool),
1316 B, 1319 B,
@@ -1321,14 +1324,14 @@ mod tests {
1321 Either::B => (), 1324 Either::B => (),
1322 } 1325 }
1323 } 1326 }
1324 "; 1327 ",
1325 1328 );
1326 check_diagnostic(content);
1327 } 1329 }
1328 1330
1329 #[test] 1331 #[test]
1330 fn enum_containing_bool_no_diagnostic() { 1332 fn enum_containing_bool_no_diagnostic() {
1331 let content = r" 1333 check_no_diagnostic(
1334 r"
1332 enum Either { 1335 enum Either {
1333 A(bool), 1336 A(bool),
1334 B, 1337 B,
@@ -1340,14 +1343,14 @@ mod tests {
1340 Either::B => (), 1343 Either::B => (),
1341 } 1344 }
1342 } 1345 }
1343 "; 1346 ",
1344 1347 );
1345 check_no_diagnostic(content);
1346 } 1348 }
1347 1349
1348 #[test] 1350 #[test]
1349 fn enum_containing_bool_with_wild_no_diagnostic() { 1351 fn enum_containing_bool_with_wild_no_diagnostic() {
1350 let content = r" 1352 check_no_diagnostic(
1353 r"
1351 enum Either { 1354 enum Either {
1352 A(bool), 1355 A(bool),
1353 B, 1356 B,
@@ -1358,14 +1361,14 @@ mod tests {
1358 _ => (), 1361 _ => (),
1359 } 1362 }
1360 } 1363 }
1361 "; 1364 ",
1362 1365 );
1363 check_no_diagnostic(content);
1364 } 1366 }
1365 1367
1366 #[test] 1368 #[test]
1367 fn enum_containing_bool_with_wild_2_no_diagnostic() { 1369 fn enum_containing_bool_with_wild_2_no_diagnostic() {
1368 let content = r" 1370 check_no_diagnostic(
1371 r"
1369 enum Either { 1372 enum Either {
1370 A(bool), 1373 A(bool),
1371 B, 1374 B,
@@ -1376,14 +1379,14 @@ mod tests {
1376 Either::B => (), 1379 Either::B => (),
1377 } 1380 }
1378 } 1381 }
1379 "; 1382 ",
1380 1383 );
1381 check_no_diagnostic(content);
1382 } 1384 }
1383 1385
1384 #[test] 1386 #[test]
1385 fn enum_different_sizes_missing_arms() { 1387 fn enum_different_sizes_missing_arms() {
1386 let content = r" 1388 check_diagnostic(
1389 r"
1387 enum Either { 1390 enum Either {
1388 A(bool), 1391 A(bool),
1389 B(bool, bool), 1392 B(bool, bool),
@@ -1394,14 +1397,14 @@ mod tests {
1394 Either::B(false, _) => (), 1397 Either::B(false, _) => (),
1395 } 1398 }
1396 } 1399 }
1397 "; 1400 ",
1398 1401 );
1399 check_diagnostic(content);
1400 } 1402 }
1401 1403
1402 #[test] 1404 #[test]
1403 fn enum_different_sizes_no_diagnostic() { 1405 fn enum_different_sizes_no_diagnostic() {
1404 let content = r" 1406 check_no_diagnostic(
1407 r"
1405 enum Either { 1408 enum Either {
1406 A(bool), 1409 A(bool),
1407 B(bool, bool), 1410 B(bool, bool),
@@ -1413,14 +1416,14 @@ mod tests {
1413 Either::B(false, _) => (), 1416 Either::B(false, _) => (),
1414 } 1417 }
1415 } 1418 }
1416 "; 1419 ",
1417 1420 );
1418 check_no_diagnostic(content);
1419 } 1421 }
1420 1422
1421 #[test] 1423 #[test]
1422 fn or_no_diagnostic() { 1424 fn or_no_diagnostic() {
1423 let content = r" 1425 check_no_diagnostic(
1426 r"
1424 enum Either { 1427 enum Either {
1425 A(bool), 1428 A(bool),
1426 B(bool, bool), 1429 B(bool, bool),
@@ -1432,14 +1435,14 @@ mod tests {
1432 Either::B(false, _) => (), 1435 Either::B(false, _) => (),
1433 } 1436 }
1434 } 1437 }
1435 "; 1438 ",
1436 1439 );
1437 check_no_diagnostic(content);
1438 } 1440 }
1439 1441
1440 #[test] 1442 #[test]
1441 fn tuple_of_enum_no_diagnostic() { 1443 fn tuple_of_enum_no_diagnostic() {
1442 let content = r" 1444 check_no_diagnostic(
1445 r"
1443 enum Either { 1446 enum Either {
1444 A(bool), 1447 A(bool),
1445 B(bool, bool), 1448 B(bool, bool),
@@ -1456,14 +1459,16 @@ mod tests {
1456 (Either::B(_, _), Either2::D) => (), 1459 (Either::B(_, _), Either2::D) => (),
1457 } 1460 }
1458 } 1461 }
1459 "; 1462 ",
1460 1463 );
1461 check_no_diagnostic(content);
1462 } 1464 }
1463 1465
1464 #[test] 1466 #[test]
1465 fn mismatched_types() { 1467 fn mismatched_types() {
1466 let content = r" 1468 // Match statements with arms that don't match the
1469 // expression pattern do not fire this diagnostic.
1470 check_no_diagnostic(
1471 r"
1467 enum Either { 1472 enum Either {
1468 A, 1473 A,
1469 B, 1474 B,
@@ -1478,47 +1483,47 @@ mod tests {
1478 Either2::D => (), 1483 Either2::D => (),
1479 } 1484 }
1480 } 1485 }
1481 "; 1486 ",
1482 1487 );
1483 // Match statements with arms that don't match the
1484 // expression pattern do not fire this diagnostic.
1485 check_no_diagnostic(content);
1486 } 1488 }
1487 1489
1488 #[test] 1490 #[test]
1489 fn mismatched_types_with_different_arity() { 1491 fn mismatched_types_with_different_arity() {
1490 let content = r" 1492 // Match statements with arms that don't match the
1493 // expression pattern do not fire this diagnostic.
1494 check_no_diagnostic(
1495 r"
1491 fn test_fn() { 1496 fn test_fn() {
1492 match (true, false) { 1497 match (true, false) {
1493 (true, false, true) => (), 1498 (true, false, true) => (),
1494 (true) => (), 1499 (true) => (),
1495 } 1500 }
1496 } 1501 }
1497 "; 1502 ",
1498 1503 );
1499 // Match statements with arms that don't match the
1500 // expression pattern do not fire this diagnostic.
1501 check_no_diagnostic(content);
1502 } 1504 }
1503 1505
1504 #[test] 1506 #[test]
1505 fn malformed_match_arm_tuple_missing_pattern() { 1507 fn malformed_match_arm_tuple_missing_pattern() {
1506 let content = r" 1508 // Match statements with arms that don't match the
1509 // expression pattern do not fire this diagnostic.
1510 check_no_diagnostic(
1511 r"
1507 fn test_fn() { 1512 fn test_fn() {
1508 match (0) { 1513 match (0) {
1509 () => (), 1514 () => (),
1510 } 1515 }
1511 } 1516 }
1512 "; 1517 ",
1513 1518 );
1514 // Match statements with arms that don't match the
1515 // expression pattern do not fire this diagnostic.
1516 check_no_diagnostic(content);
1517 } 1519 }
1518 1520
1519 #[test] 1521 #[test]
1520 fn malformed_match_arm_tuple_enum_missing_pattern() { 1522 fn malformed_match_arm_tuple_enum_missing_pattern() {
1521 let content = r" 1523 // We are testing to be sure we don't panic here when the match
1524 // arm `Either::B` is missing its pattern.
1525 check_no_diagnostic(
1526 r"
1522 enum Either { 1527 enum Either {
1523 A, 1528 A,
1524 B(u32), 1529 B(u32),
@@ -1529,32 +1534,30 @@ mod tests {
1529 Either::B() => (), 1534 Either::B() => (),
1530 } 1535 }
1531 } 1536 }
1532 "; 1537 ",
1533 1538 );
1534 // We are testing to be sure we don't panic here when the match
1535 // arm `Either::B` is missing its pattern.
1536 check_no_diagnostic(content);
1537 } 1539 }
1538 1540
1539 #[test] 1541 #[test]
1540 fn enum_not_in_scope() { 1542 fn enum_not_in_scope() {
1541 let content = r" 1543 // The enum is not in scope so we don't perform exhaustiveness
1544 // checking, but we want to be sure we don't panic here (and
1545 // we don't create a diagnostic).
1546 check_no_diagnostic(
1547 r"
1542 fn test_fn() { 1548 fn test_fn() {
1543 match Foo::Bar { 1549 match Foo::Bar {
1544 Foo::Baz => (), 1550 Foo::Baz => (),
1545 } 1551 }
1546 } 1552 }
1547 "; 1553 ",
1548 1554 );
1549 // The enum is not in scope so we don't perform exhaustiveness
1550 // checking, but we want to be sure we don't panic here (and
1551 // we don't create a diagnostic).
1552 check_no_diagnostic(content);
1553 } 1555 }
1554 1556
1555 #[test] 1557 #[test]
1556 fn expr_diverges() { 1558 fn expr_diverges() {
1557 let content = r" 1559 check_no_diagnostic(
1560 r"
1558 enum Either { 1561 enum Either {
1559 A, 1562 A,
1560 B, 1563 B,
@@ -1565,14 +1568,14 @@ mod tests {
1565 Either::B => (), 1568 Either::B => (),
1566 } 1569 }
1567 } 1570 }
1568 "; 1571 ",
1569 1572 );
1570 check_no_diagnostic(content);
1571 } 1573 }
1572 1574
1573 #[test] 1575 #[test]
1574 fn expr_loop_with_break() { 1576 fn expr_loop_with_break() {
1575 let content = r" 1577 check_no_diagnostic(
1578 r"
1576 enum Either { 1579 enum Either {
1577 A, 1580 A,
1578 B, 1581 B,
@@ -1583,14 +1586,14 @@ mod tests {
1583 Either::B => (), 1586 Either::B => (),
1584 } 1587 }
1585 } 1588 }
1586 "; 1589 ",
1587 1590 );
1588 check_no_diagnostic(content);
1589 } 1591 }
1590 1592
1591 #[test] 1593 #[test]
1592 fn expr_partially_diverges() { 1594 fn expr_partially_diverges() {
1593 let content = r" 1595 check_no_diagnostic(
1596 r"
1594 enum Either<T> { 1597 enum Either<T> {
1595 A(T), 1598 A(T),
1596 B, 1599 B,
@@ -1604,14 +1607,14 @@ mod tests {
1604 Either::B => 0, 1607 Either::B => 0,
1605 } 1608 }
1606 } 1609 }
1607 "; 1610 ",
1608 1611 );
1609 check_no_diagnostic(content);
1610 } 1612 }
1611 1613
1612 #[test] 1614 #[test]
1613 fn enum_record_no_arms() { 1615 fn enum_record_no_arms() {
1614 let content = r" 1616 check_diagnostic(
1617 r"
1615 enum Either { 1618 enum Either {
1616 A { foo: bool }, 1619 A { foo: bool },
1617 B, 1620 B,
@@ -1621,14 +1624,14 @@ mod tests {
1621 match a { 1624 match a {
1622 } 1625 }
1623 } 1626 }
1624 "; 1627 ",
1625 1628 );
1626 check_diagnostic(content);
1627 } 1629 }
1628 1630
1629 #[test] 1631 #[test]
1630 fn enum_record_missing_arms() { 1632 fn enum_record_missing_arms() {
1631 let content = r" 1633 check_diagnostic(
1634 r"
1632 enum Either { 1635 enum Either {
1633 A { foo: bool }, 1636 A { foo: bool },
1634 B, 1637 B,
@@ -1639,14 +1642,14 @@ mod tests {
1639 Either::A { foo: true } => (), 1642 Either::A { foo: true } => (),
1640 } 1643 }
1641 } 1644 }
1642 "; 1645 ",
1643 1646 );
1644 check_diagnostic(content);
1645 } 1647 }
1646 1648
1647 #[test] 1649 #[test]
1648 fn enum_record_no_diagnostic() { 1650 fn enum_record_no_diagnostic() {
1649 let content = r" 1651 check_no_diagnostic(
1652 r"
1650 enum Either { 1653 enum Either {
1651 A { foo: bool }, 1654 A { foo: bool },
1652 B, 1655 B,
@@ -1659,14 +1662,17 @@ mod tests {
1659 Either::B => (), 1662 Either::B => (),
1660 } 1663 }
1661 } 1664 }
1662 "; 1665 ",
1663 1666 );
1664 check_no_diagnostic(content);
1665 } 1667 }
1666 1668
1667 #[test] 1669 #[test]
1668 fn enum_record_missing_field_no_diagnostic() { 1670 fn enum_record_missing_field_no_diagnostic() {
1669 let content = r" 1671 // When `Either::A` is missing a struct member, we don't want
1672 // to fire the missing match arm diagnostic. This should fire
1673 // some other diagnostic.
1674 check_no_diagnostic(
1675 r"
1670 enum Either { 1676 enum Either {
1671 A { foo: bool }, 1677 A { foo: bool },
1672 B, 1678 B,
@@ -1678,17 +1684,16 @@ mod tests {
1678 Either::B => (), 1684 Either::B => (),
1679 } 1685 }
1680 } 1686 }
1681 "; 1687 ",
1682 1688 );
1683 // When `Either::A` is missing a struct member, we don't want
1684 // to fire the missing match arm diagnostic. This should fire
1685 // some other diagnostic.
1686 check_no_diagnostic(content);
1687 } 1689 }
1688 1690
1689 #[test] 1691 #[test]
1690 fn enum_record_missing_field_missing_match_arm() { 1692 fn enum_record_missing_field_missing_match_arm() {
1691 let content = r" 1693 // Even though `Either::A` is missing fields, we still want to fire
1694 // the missing arm diagnostic here, since we know `Either::B` is missing.
1695 check_diagnostic(
1696 r"
1692 enum Either { 1697 enum Either {
1693 A { foo: bool }, 1698 A { foo: bool },
1694 B, 1699 B,
@@ -1699,16 +1704,14 @@ mod tests {
1699 Either::A { } => (), 1704 Either::A { } => (),
1700 } 1705 }
1701 } 1706 }
1702 "; 1707 ",
1703 1708 );
1704 // Even though `Either::A` is missing fields, we still want to fire
1705 // the missing arm diagnostic here, since we know `Either::B` is missing.
1706 check_diagnostic(content);
1707 } 1709 }
1708 1710
1709 #[test] 1711 #[test]
1710 fn enum_record_no_diagnostic_wild() { 1712 fn enum_record_no_diagnostic_wild() {
1711 let content = r" 1713 check_no_diagnostic(
1714 r"
1712 enum Either { 1715 enum Either {
1713 A { foo: bool }, 1716 A { foo: bool },
1714 B, 1717 B,
@@ -1720,14 +1723,14 @@ mod tests {
1720 Either::B => (), 1723 Either::B => (),
1721 } 1724 }
1722 } 1725 }
1723 "; 1726 ",
1724 1727 );
1725 check_no_diagnostic(content);
1726 } 1728 }
1727 1729
1728 #[test] 1730 #[test]
1729 fn enum_record_fields_out_of_order_missing_arm() { 1731 fn enum_record_fields_out_of_order_missing_arm() {
1730 let content = r" 1732 check_diagnostic(
1733 r"
1731 enum Either { 1734 enum Either {
1732 A { foo: bool, bar: () }, 1735 A { foo: bool, bar: () },
1733 B, 1736 B,
@@ -1739,14 +1742,14 @@ mod tests {
1739 Either::A { foo: true, bar: () } => (), 1742 Either::A { foo: true, bar: () } => (),
1740 } 1743 }
1741 } 1744 }
1742 "; 1745 ",
1743 1746 );
1744 check_diagnostic(content);
1745 } 1747 }
1746 1748
1747 #[test] 1749 #[test]
1748 fn enum_record_fields_out_of_order_no_diagnostic() { 1750 fn enum_record_fields_out_of_order_no_diagnostic() {
1749 let content = r" 1751 check_no_diagnostic(
1752 r"
1750 enum Either { 1753 enum Either {
1751 A { foo: bool, bar: () }, 1754 A { foo: bool, bar: () },
1752 B, 1755 B,
@@ -1759,89 +1762,89 @@ mod tests {
1759 Either::B => (), 1762 Either::B => (),
1760 } 1763 }
1761 } 1764 }
1762 "; 1765 ",
1763 1766 );
1764 check_no_diagnostic(content);
1765 } 1767 }
1766 1768
1767 #[test] 1769 #[test]
1768 fn enum_record_ellipsis_missing_arm() { 1770 fn enum_record_ellipsis_missing_arm() {
1769 let content = r" 1771 check_diagnostic(
1770 enum Either { 1772 r"
1771 A { foo: bool, bar: bool }, 1773 enum Either {
1772 B, 1774 A { foo: bool, bar: bool },
1773 } 1775 B,
1774 fn test_fn() { 1776 }
1775 match Either::B { 1777 fn test_fn() {
1776 Either::A { foo: true, .. } => (), 1778 match Either::B {
1777 Either::B => (), 1779 Either::A { foo: true, .. } => (),
1778 } 1780 Either::B => (),
1779 } 1781 }
1780 "; 1782 }
1781 1783 ",
1782 check_diagnostic(content); 1784 );
1783 } 1785 }
1784 1786
1785 #[test] 1787 #[test]
1786 fn enum_record_ellipsis_no_diagnostic() { 1788 fn enum_record_ellipsis_no_diagnostic() {
1787 let content = r" 1789 check_no_diagnostic(
1788 enum Either { 1790 r"
1789 A { foo: bool, bar: bool }, 1791 enum Either {
1790 B, 1792 A { foo: bool, bar: bool },
1791 } 1793 B,
1792 fn test_fn() { 1794 }
1793 let a = Either::A { foo: true }; 1795 fn test_fn() {
1794 match a { 1796 let a = Either::A { foo: true };
1795 Either::A { foo: true, .. } => (), 1797 match a {
1796 Either::A { foo: false, .. } => (), 1798 Either::A { foo: true, .. } => (),
1797 Either::B => (), 1799 Either::A { foo: false, .. } => (),
1798 } 1800 Either::B => (),
1799 } 1801 }
1800 "; 1802 }
1801 1803 ",
1802 check_no_diagnostic(content); 1804 );
1803 } 1805 }
1804 1806
1805 #[test] 1807 #[test]
1806 fn enum_record_ellipsis_all_fields_missing_arm() { 1808 fn enum_record_ellipsis_all_fields_missing_arm() {
1807 let content = r" 1809 check_diagnostic(
1808 enum Either { 1810 r"
1809 A { foo: bool, bar: bool }, 1811 enum Either {
1810 B, 1812 A { foo: bool, bar: bool },
1811 } 1813 B,
1812 fn test_fn() { 1814 }
1813 let a = Either::B; 1815 fn test_fn() {
1814 match a { 1816 let a = Either::B;
1815 Either::A { .. } => (), 1817 match a {
1816 } 1818 Either::A { .. } => (),
1817 } 1819 }
1818 "; 1820 }
1819 1821 ",
1820 check_diagnostic(content); 1822 );
1821 } 1823 }
1822 1824
1823 #[test] 1825 #[test]
1824 fn enum_record_ellipsis_all_fields_no_diagnostic() { 1826 fn enum_record_ellipsis_all_fields_no_diagnostic() {
1825 let content = r" 1827 check_no_diagnostic(
1826 enum Either { 1828 r"
1827 A { foo: bool, bar: bool }, 1829 enum Either {
1828 B, 1830 A { foo: bool, bar: bool },
1829 } 1831 B,
1830 fn test_fn() { 1832 }
1831 let a = Either::B; 1833 fn test_fn() {
1832 match a { 1834 let a = Either::B;
1833 Either::A { .. } => (), 1835 match a {
1834 Either::B => (), 1836 Either::A { .. } => (),
1835 } 1837 Either::B => (),
1836 } 1838 }
1837 "; 1839 }
1838 1840 ",
1839 check_no_diagnostic(content); 1841 );
1840 } 1842 }
1841 1843
1842 #[test] 1844 #[test]
1843 fn enum_tuple_partial_ellipsis_no_diagnostic() { 1845 fn enum_tuple_partial_ellipsis_no_diagnostic() {
1844 let content = r" 1846 check_no_diagnostic(
1847 r"
1845 enum Either { 1848 enum Either {
1846 A(bool, bool, bool, bool), 1849 A(bool, bool, bool, bool),
1847 B, 1850 B,
@@ -1855,14 +1858,14 @@ mod tests {
1855 Either::B => {}, 1858 Either::B => {},
1856 } 1859 }
1857 } 1860 }
1858 "; 1861 ",
1859 1862 );
1860 check_no_diagnostic(content);
1861 } 1863 }
1862 1864
1863 #[test] 1865 #[test]
1864 fn enum_tuple_partial_ellipsis_2_no_diagnostic() { 1866 fn enum_tuple_partial_ellipsis_2_no_diagnostic() {
1865 let content = r" 1867 check_no_diagnostic(
1868 r"
1866 enum Either { 1869 enum Either {
1867 A(bool, bool, bool, bool), 1870 A(bool, bool, bool, bool),
1868 B, 1871 B,
@@ -1876,14 +1879,14 @@ mod tests {
1876 Either::B => {}, 1879 Either::B => {},
1877 } 1880 }
1878 } 1881 }
1879 "; 1882 ",
1880 1883 );
1881 check_no_diagnostic(content);
1882 } 1884 }
1883 1885
1884 #[test] 1886 #[test]
1885 fn enum_tuple_partial_ellipsis_missing_arm() { 1887 fn enum_tuple_partial_ellipsis_missing_arm() {
1886 let content = r" 1888 check_diagnostic(
1889 r"
1887 enum Either { 1890 enum Either {
1888 A(bool, bool, bool, bool), 1891 A(bool, bool, bool, bool),
1889 B, 1892 B,
@@ -1896,14 +1899,14 @@ mod tests {
1896 Either::B => {}, 1899 Either::B => {},
1897 } 1900 }
1898 } 1901 }
1899 "; 1902 ",
1900 1903 );
1901 check_diagnostic(content);
1902 } 1904 }
1903 1905
1904 #[test] 1906 #[test]
1905 fn enum_tuple_partial_ellipsis_2_missing_arm() { 1907 fn enum_tuple_partial_ellipsis_2_missing_arm() {
1906 let content = r" 1908 check_diagnostic(
1909 r"
1907 enum Either { 1910 enum Either {
1908 A(bool, bool, bool, bool), 1911 A(bool, bool, bool, bool),
1909 B, 1912 B,
@@ -1916,14 +1919,14 @@ mod tests {
1916 Either::B => {}, 1919 Either::B => {},
1917 } 1920 }
1918 } 1921 }
1919 "; 1922 ",
1920 1923 );
1921 check_diagnostic(content);
1922 } 1924 }
1923 1925
1924 #[test] 1926 #[test]
1925 fn enum_tuple_ellipsis_no_diagnostic() { 1927 fn enum_tuple_ellipsis_no_diagnostic() {
1926 let content = r" 1928 check_no_diagnostic(
1929 r"
1927 enum Either { 1930 enum Either {
1928 A(bool, bool, bool, bool), 1931 A(bool, bool, bool, bool),
1929 B, 1932 B,
@@ -1934,51 +1937,51 @@ mod tests {
1934 Either::B => {}, 1937 Either::B => {},
1935 } 1938 }
1936 } 1939 }
1937 "; 1940 ",
1938 1941 );
1939 check_no_diagnostic(content);
1940 } 1942 }
1941 1943
1942 #[test] 1944 #[test]
1943 fn enum_never() { 1945 fn enum_never() {
1944 let content = r" 1946 check_no_diagnostic(
1947 r"
1945 enum Never {} 1948 enum Never {}
1946 1949
1947 fn test_fn(never: Never) { 1950 fn test_fn(never: Never) {
1948 match never {} 1951 match never {}
1949 } 1952 }
1950 "; 1953 ",
1951 1954 );
1952 check_no_diagnostic(content);
1953 } 1955 }
1954 1956
1955 #[test] 1957 #[test]
1956 fn type_never() { 1958 fn type_never() {
1957 let content = r" 1959 check_no_diagnostic(
1960 r"
1958 fn test_fn(never: !) { 1961 fn test_fn(never: !) {
1959 match never {} 1962 match never {}
1960 } 1963 }
1961 "; 1964 ",
1962 1965 );
1963 check_no_diagnostic(content);
1964 } 1966 }
1965 1967
1966 #[test] 1968 #[test]
1967 fn enum_never_ref() { 1969 fn enum_never_ref() {
1968 let content = r" 1970 check_no_diagnostic(
1971 r"
1969 enum Never {} 1972 enum Never {}
1970 1973
1971 fn test_fn(never: &Never) { 1974 fn test_fn(never: &Never) {
1972 match never {} 1975 match never {}
1973 } 1976 }
1974 "; 1977 ",
1975 1978 );
1976 check_no_diagnostic(content);
1977 } 1979 }
1978 1980
1979 #[test] 1981 #[test]
1980 fn expr_diverges_missing_arm() { 1982 fn expr_diverges_missing_arm() {
1981 let content = r" 1983 check_no_diagnostic(
1984 r"
1982 enum Either { 1985 enum Either {
1983 A, 1986 A,
1984 B, 1987 B,
@@ -1988,9 +1991,49 @@ mod tests {
1988 Either::A => (), 1991 Either::A => (),
1989 } 1992 }
1990 } 1993 }
1991 "; 1994 ",
1995 );
1996 }
1992 1997
1993 check_no_diagnostic(content); 1998 #[test]
1999 fn or_pattern_panic() {
2000 check_no_diagnostic(
2001 r"
2002 pub enum Category {
2003 Infinity,
2004 Zero,
2005 }
2006
2007 fn panic(a: Category, b: Category) {
2008 match (a, b) {
2009 (Category::Zero | Category::Infinity, _) => {}
2010 (_, Category::Zero | Category::Infinity) => {}
2011 }
2012 }
2013 ",
2014 );
2015 }
2016
2017 #[test]
2018 fn or_pattern_panic_2() {
2019 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
2020 // so this acts as a regression test for that.
2021 check_diagnostic(
2022 r"
2023 pub enum Category {
2024 Infinity,
2025 Zero,
2026 }
2027
2028 fn panic(a: Category, b: Category) {
2029 match (a, b) {
2030 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {}
2031
2032 (Category::Infinity | Category::Zero, _) => {}
2033 }
2034 }
2035 ",
2036 );
1994 } 2037 }
1995} 2038}
1996 2039
@@ -2010,23 +2053,26 @@ mod false_negatives {
2010 2053
2011 #[test] 2054 #[test]
2012 fn integers() { 2055 fn integers() {
2013 let content = r" 2056 // This is a false negative.
2057 // We don't currently check integer exhaustiveness.
2058 check_no_diagnostic(
2059 r"
2014 fn test_fn() { 2060 fn test_fn() {
2015 match 5 { 2061 match 5 {
2016 10 => (), 2062 10 => (),
2017 11..20 => (), 2063 11..20 => (),
2018 } 2064 }
2019 } 2065 }
2020 "; 2066 ",
2021 2067 );
2022 // This is a false negative.
2023 // We don't currently check integer exhaustiveness.
2024 check_no_diagnostic(content);
2025 } 2068 }
2026 2069
2027 #[test] 2070 #[test]
2028 fn internal_or() { 2071 fn internal_or() {
2029 let content = r" 2072 // This is a false negative.
2073 // We do not currently handle patterns with internal `or`s.
2074 check_no_diagnostic(
2075 r"
2030 fn test_fn() { 2076 fn test_fn() {
2031 enum Either { 2077 enum Either {
2032 A(bool), 2078 A(bool),
@@ -2036,16 +2082,18 @@ mod false_negatives {
2036 Either::A(true | false) => (), 2082 Either::A(true | false) => (),
2037 } 2083 }
2038 } 2084 }
2039 "; 2085 ",
2040 2086 );
2041 // This is a false negative.
2042 // We do not currently handle patterns with internal `or`s.
2043 check_no_diagnostic(content);
2044 } 2087 }
2045 2088
2046 #[test] 2089 #[test]
2047 fn expr_loop_missing_arm() { 2090 fn expr_loop_missing_arm() {
2048 let content = r" 2091 // This is a false negative.
2092 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2093 // causes us to skip the diagnostic since `Either::A` doesn't type check
2094 // with `!`.
2095 check_diagnostic(
2096 r"
2049 enum Either { 2097 enum Either {
2050 A, 2098 A,
2051 B, 2099 B,
@@ -2055,48 +2103,46 @@ mod false_negatives {
2055 Either::A => (), 2103 Either::A => (),
2056 } 2104 }
2057 } 2105 }
2058 "; 2106 ",
2059 2107 );
2060 // This is a false negative.
2061 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2062 // causes us to skip the diagnostic since `Either::A` doesn't type check
2063 // with `!`.
2064 check_diagnostic(content);
2065 } 2108 }
2066 2109
2067 #[test] 2110 #[test]
2068 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { 2111 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
2069 let content = r" 2112 // This is a false negative.
2113 // We don't currently handle tuple patterns with ellipsis.
2114 check_no_diagnostic(
2115 r"
2070 fn test_fn() { 2116 fn test_fn() {
2071 match (false, true, false) { 2117 match (false, true, false) {
2072 (false, ..) => {}, 2118 (false, ..) => {},
2073 } 2119 }
2074 } 2120 }
2075 "; 2121 ",
2076 2122 );
2077 // This is a false negative.
2078 // We don't currently handle tuple patterns with ellipsis.
2079 check_no_diagnostic(content);
2080 } 2123 }
2081 2124
2082 #[test] 2125 #[test]
2083 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { 2126 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() {
2084 let content = r" 2127 // This is a false negative.
2128 // We don't currently handle tuple patterns with ellipsis.
2129 check_no_diagnostic(
2130 r"
2085 fn test_fn() { 2131 fn test_fn() {
2086 match (false, true, false) { 2132 match (false, true, false) {
2087 (.., false) => {}, 2133 (.., false) => {},
2088 } 2134 }
2089 } 2135 }
2090 "; 2136 ",
2091 2137 );
2092 // This is a false negative.
2093 // We don't currently handle tuple patterns with ellipsis.
2094 check_no_diagnostic(content);
2095 } 2138 }
2096 2139
2097 #[test] 2140 #[test]
2098 fn struct_missing_arm() { 2141 fn struct_missing_arm() {
2099 let content = r" 2142 // This is a false negative.
2143 // We don't currently handle structs.
2144 check_no_diagnostic(
2145 r"
2100 struct Foo { 2146 struct Foo {
2101 a: bool, 2147 a: bool,
2102 } 2148 }
@@ -2105,10 +2151,7 @@ mod false_negatives {
2105 Foo { a: true } => {}, 2151 Foo { a: true } => {},
2106 } 2152 }
2107 } 2153 }
2108 "; 2154 ",
2109 2155 );
2110 // This is a false negative.
2111 // We don't currently handle structs.
2112 check_no_diagnostic(content);
2113 } 2156 }
2114} 2157}
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index bf71d38d6..7889b8d2c 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,15 +3,15 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId, 6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId,
7 TypeParamId, VariantId, 7 VariantId,
8}; 8};
9use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
10use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; 10use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
11use ra_prof::profile; 11use ra_prof::profile;
12 12
13use crate::{ 13use crate::{
14 method_resolution::{CrateImplDefs, TyFingerprint}, 14 method_resolution::CrateImplDefs,
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
@@ -70,13 +70,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] 70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; 71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
72 72
73 #[salsa::invoke(crate::traits::impls_for_trait_query)] 73 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)]
74 fn impls_for_trait( 74 fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>;
75 &self,
76 krate: CrateId,
77 trait_: TraitId,
78 self_ty_fp: Option<TyFingerprint>,
79 ) -> Arc<[ImplId]>;
80 75
81 // Interned IDs for Chalk integration 76 // Interned IDs for Chalk integration
82 #[salsa::interned] 77 #[salsa::interned]
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 2c7298714..ebd9cb08f 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,7 +6,7 @@ use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7use stdx::format_to; 7use stdx::format_to;
8 8
9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm}; 9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path};
10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
11 11
12#[derive(Debug)] 12#[derive(Debug)]
@@ -29,6 +29,16 @@ impl Diagnostic for NoSuchField {
29 } 29 }
30} 30}
31 31
32impl AstDiagnostic for NoSuchField {
33 type AST = ast::RecordField;
34
35 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
36 let root = db.parse_or_expand(self.source().file_id).unwrap();
37 let node = self.source().value.to_node(&root);
38 ast::RecordField::cast(node).unwrap()
39 }
40}
41
32#[derive(Debug)] 42#[derive(Debug)]
33pub struct MissingFields { 43pub struct MissingFields {
34 pub file: HirFileId, 44 pub file: HirFileId,
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 9fd310f69..a9565a58d 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -10,12 +10,12 @@ use hir_def::{
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, AssocContainerId, FieldId, Lookup, 11 AdtId, AssocContainerId, FieldId, Lookup,
12}; 12};
13use hir_expand::name::Name; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::InEnvironment, 18 traits::{FnTrait, InEnvironment},
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, 20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 TraitRef, Ty, TypeCtor, 21 TraitRef, Ty, TypeCtor,
@@ -63,6 +63,58 @@ impl<'a> InferenceContext<'a> {
63 self.resolve_ty_as_possible(ty) 63 self.resolve_ty_as_possible(ty)
64 } 64 }
65 65
66 fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
67 let krate = self.resolver.krate()?;
68 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
69 let output_assoc_type =
70 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
71 let generic_params = generics(self.db.upcast(), fn_once_trait.into());
72 if generic_params.len() != 2 {
73 return None;
74 }
75
76 let mut param_builder = Substs::builder(num_args);
77 let mut arg_tys = vec![];
78 for _ in 0..num_args {
79 let arg = self.table.new_type_var();
80 param_builder = param_builder.push(arg.clone());
81 arg_tys.push(arg);
82 }
83 let parameters = param_builder.build();
84 let arg_ty = Ty::Apply(ApplicationTy {
85 ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
86 parameters,
87 });
88 let substs = Substs::build_for_generics(&generic_params)
89 .push(ty.clone())
90 .push(arg_ty.clone())
91 .build();
92
93 let trait_env = Arc::clone(&self.trait_env);
94 let implements_fn_trait =
95 Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
96 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
97 value: implements_fn_trait.clone(),
98 environment: trait_env,
99 });
100 if self.db.trait_solve(krate, goal.value).is_some() {
101 self.obligations.push(implements_fn_trait);
102 let output_proj_ty =
103 crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
104 let return_ty = self.normalize_projection_ty(output_proj_ty);
105 Some((arg_tys, return_ty))
106 } else {
107 None
108 }
109 }
110
111 pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
112 match ty.callable_sig(self.db) {
113 Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
114 None => self.callable_sig_from_fn_trait(ty, num_args),
115 }
116 }
117
66 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 118 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
67 let body = Arc::clone(&self.body); // avoid borrow checker problem 119 let body = Arc::clone(&self.body); // avoid borrow checker problem
68 let ty = match &body[tgt_expr] { 120 let ty = match &body[tgt_expr] {
@@ -198,14 +250,23 @@ impl<'a> InferenceContext<'a> {
198 } 250 }
199 Expr::Call { callee, args } => { 251 Expr::Call { callee, args } => {
200 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 252 let callee_ty = self.infer_expr(*callee, &Expectation::none());
201 let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) { 253 let canonicalized = self.canonicalizer().canonicalize_ty(callee_ty.clone());
202 Some(sig) => (sig.params().to_vec(), sig.ret().clone()), 254 let mut derefs = autoderef(
203 None => { 255 self.db,
204 // Not callable 256 self.resolver.krate(),
205 // FIXME: report an error 257 InEnvironment {
206 (Vec::new(), Ty::Unknown) 258 value: canonicalized.value.clone(),
207 } 259 environment: self.trait_env.clone(),
208 }; 260 },
261 );
262 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
263 .find_map(|callee_deref_ty| {
264 self.callable_sig(
265 &canonicalized.decanonicalize_ty(callee_deref_ty.value),
266 args.len(),
267 )
268 })
269 .unwrap_or((Vec::new(), Ty::Unknown));
209 self.register_obligations_for_call(&callee_ty); 270 self.register_obligations_for_call(&callee_ty);
210 self.check_call_arguments(args, &param_tys); 271 self.check_call_arguments(args, &param_tys);
211 self.normalize_associated_types_in(ret_ty) 272 self.normalize_associated_types_in(ret_ty)
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 1ad0d8397..80d7ed10e 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -81,7 +81,7 @@ impl<'a> InferenceContext<'a> {
81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
82 let substs = Substs::type_params_for_generics(&generics); 82 let substs = Substs::type_params_for_generics(&generics);
83 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 83 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
84 if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { 84 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
85 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 85 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
86 return Some(ty); 86 return Some(ty);
87 } else { 87 } else {
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 2b9372b4b..f22232324 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -73,6 +73,7 @@ pub use lower::{
73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
74 74
75pub use chalk_ir::{BoundVar, DebruijnIndex}; 75pub use chalk_ir::{BoundVar, DebruijnIndex};
76use itertools::Itertools;
76 77
77/// A type constructor or type name: this might be something like the primitive 78/// A type constructor or type name: this might be something like the primitive
78/// type `bool`, a struct like `Vec`, or things like function pointers or 79/// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -815,6 +816,11 @@ impl Ty {
815 } 816 }
816 } 817 }
817 818
819 /// If this is a `dyn Trait`, returns that trait.
820 pub fn dyn_trait(&self) -> Option<TraitId> {
821 self.dyn_trait_ref().map(|it| it.trait_)
822 }
823
818 fn builtin_deref(&self) -> Option<Ty> { 824 fn builtin_deref(&self) -> Option<Ty> {
819 match self { 825 match self {
820 Ty::Apply(a_ty) => match a_ty.ctor { 826 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -867,13 +873,56 @@ impl Ty {
867 } 873 }
868 } 874 }
869 875
870 /// If this is a `dyn Trait`, returns that trait. 876 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
871 pub fn dyn_trait(&self) -> Option<TraitId> {
872 match self { 877 match self {
873 Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { 878 Ty::Opaque(opaque_ty) => {
874 GenericPredicate::Implemented(tr) => Some(tr.trait_), 879 let predicates = match opaque_ty.opaque_ty_id {
875 _ => None, 880 OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
876 }), 881 db.return_type_impl_traits(func).map(|it| {
882 let data = (*it)
883 .as_ref()
884 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
885 data.clone().subst(&opaque_ty.parameters)
886 })
887 }
888 };
889
890 predicates.map(|it| it.value)
891 }
892 Ty::Placeholder(id) => {
893 let generic_params = db.generic_params(id.parent);
894 let param_data = &generic_params.types[id.local_id];
895 match param_data.provenance {
896 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
897 let predicates = db
898 .generic_predicates_for_param(*id)
899 .into_iter()
900 .map(|pred| pred.value.clone())
901 .collect_vec();
902
903 Some(predicates)
904 }
905 _ => None,
906 }
907 }
908 _ => None,
909 }
910 }
911
912 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
913 match self {
914 Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => {
915 match type_alias_id.lookup(db.upcast()).container {
916 AssocContainerId::TraitId(trait_id) => Some(trait_id),
917 _ => None,
918 }
919 }
920 Ty::Projection(projection_ty) => {
921 match projection_ty.associated_ty.lookup(db.upcast()).container {
922 AssocContainerId::TraitId(trait_id) => Some(trait_id),
923 _ => None,
924 }
925 }
877 _ => None, 926 _ => None,
878 } 927 }
879 } 928 }
@@ -1057,5 +1106,5 @@ pub struct ReturnTypeImplTraits {
1057 1106
1058#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1107#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1059pub(crate) struct ReturnTypeImplTrait { 1108pub(crate) struct ReturnTypeImplTrait {
1060 pub(crate) bounds: Binders<Vec<GenericPredicate>>, 1109 pub bounds: Binders<Vec<GenericPredicate>>,
1061} 1110}
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 42713928f..d5154f436 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -337,17 +337,17 @@ impl Ty {
337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
338 let ty = if remaining_segments.len() == 1 { 338 let ty = if remaining_segments.len() == 1 {
339 let segment = remaining_segments.first().unwrap(); 339 let segment = remaining_segments.first().unwrap();
340 let associated_ty = associated_type_by_name_including_super_traits( 340 let found = associated_type_by_name_including_super_traits(
341 ctx.db.upcast(), 341 ctx.db,
342 trait_ref.trait_, 342 trait_ref.clone(),
343 &segment.name, 343 &segment.name,
344 ); 344 );
345 match associated_ty { 345 match found {
346 Some(associated_ty) => { 346 Some((super_trait_ref, associated_ty)) => {
347 // FIXME handle type parameters on the segment 347 // FIXME handle type parameters on the segment
348 Ty::Projection(ProjectionTy { 348 Ty::Projection(ProjectionTy {
349 associated_ty, 349 associated_ty,
350 parameters: trait_ref.substs, 350 parameters: super_trait_ref.substs,
351 }) 351 })
352 } 352 }
353 None => { 353 None => {
@@ -467,6 +467,9 @@ impl Ty {
467 } 467 }
468 TypeParamLoweringMode::Variable => t.substs.clone(), 468 TypeParamLoweringMode::Variable => t.substs.clone(),
469 }; 469 };
470 // We need to shift in the bound vars, since
471 // associated_type_shorthand_candidates does not do that
472 let substs = substs.shift_bound_vars(ctx.in_binders);
470 // FIXME handle type parameters on the segment 473 // FIXME handle type parameters on the segment
471 return Some(Ty::Projection(ProjectionTy { 474 return Some(Ty::Projection(ProjectionTy {
472 associated_ty, 475 associated_ty,
@@ -706,17 +709,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
706 .flat_map(|segment| segment.args_and_bindings.into_iter()) 709 .flat_map(|segment| segment.args_and_bindings.into_iter())
707 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 710 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
708 .flat_map(move |binding| { 711 .flat_map(move |binding| {
709 let associated_ty = associated_type_by_name_including_super_traits( 712 let found = associated_type_by_name_including_super_traits(
710 ctx.db.upcast(), 713 ctx.db,
711 trait_ref.trait_, 714 trait_ref.clone(),
712 &binding.name, 715 &binding.name,
713 ); 716 );
714 let associated_ty = match associated_ty { 717 let (super_trait_ref, associated_ty) = match found {
715 None => return SmallVec::<[GenericPredicate; 1]>::new(), 718 None => return SmallVec::<[GenericPredicate; 1]>::new(),
716 Some(t) => t, 719 Some(t) => t,
717 }; 720 };
718 let projection_ty = 721 let projection_ty =
719 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 722 ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
720 let mut preds = SmallVec::with_capacity( 723 let mut preds = SmallVec::with_capacity(
721 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 724 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
722 ); 725 );
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index e83b39456..ed638c195 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -38,18 +38,53 @@ impl TyFingerprint {
38 } 38 }
39} 39}
40 40
41/// A queryable and mergeable collection of impls.
41#[derive(Debug, PartialEq, Eq)] 42#[derive(Debug, PartialEq, Eq)]
42pub struct CrateImplDefs { 43pub struct CrateImplDefs {
43 impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 44 inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
44 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, 45 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
45} 46}
46 47
47impl CrateImplDefs { 48impl CrateImplDefs {
48 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { 49 pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
49 let _p = profile("impls_in_crate_query"); 50 let _p = profile("impls_in_crate_query");
50 let mut res = 51 let mut res = CrateImplDefs {
51 CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; 52 inherent_impls: FxHashMap::default(),
53 impls_by_trait: FxHashMap::default(),
54 };
55 res.fill(db, krate);
56
57 Arc::new(res)
58 }
59
60 /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61 ///
62 /// The full set of impls that can be used by `krate` is the returned map plus all the impls
63 /// from `krate` itself.
64 pub(crate) fn impls_from_deps_query(
65 db: &dyn HirDatabase,
66 krate: CrateId,
67 ) -> Arc<CrateImplDefs> {
68 let _p = profile("impls_from_deps_query");
69 let crate_graph = db.crate_graph();
70 let mut res = CrateImplDefs {
71 inherent_impls: FxHashMap::default(),
72 impls_by_trait: FxHashMap::default(),
73 };
52 74
75 // For each dependency, calculate `impls_from_deps` recursively, then add its own
76 // `impls_in_crate`.
77 // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid
78 // wasting memory.
79 for dep in &crate_graph[krate].dependencies {
80 res.merge(&db.impls_from_deps(dep.crate_id));
81 res.merge(&db.impls_in_crate(dep.crate_id));
82 }
83
84 Arc::new(res)
85 }
86
87 fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
53 let crate_def_map = db.crate_def_map(krate); 88 let crate_def_map = db.crate_def_map(krate);
54 for (_module_id, module_data) in crate_def_map.modules.iter() { 89 for (_module_id, module_data) in crate_def_map.modules.iter() {
55 for impl_id in module_data.scope.impls() { 90 for impl_id in module_data.scope.impls() {
@@ -57,7 +92,7 @@ impl CrateImplDefs {
57 Some(tr) => { 92 Some(tr) => {
58 let self_ty = db.impl_self_ty(impl_id); 93 let self_ty = db.impl_self_ty(impl_id);
59 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); 94 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
60 res.impls_by_trait 95 self.impls_by_trait
61 .entry(tr.value.trait_) 96 .entry(tr.value.trait_)
62 .or_default() 97 .or_default()
63 .entry(self_ty_fp) 98 .entry(self_ty_fp)
@@ -67,18 +102,36 @@ impl CrateImplDefs {
67 None => { 102 None => {
68 let self_ty = db.impl_self_ty(impl_id); 103 let self_ty = db.impl_self_ty(impl_id);
69 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { 104 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
70 res.impls.entry(self_ty_fp).or_default().push(impl_id); 105 self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
71 } 106 }
72 } 107 }
73 } 108 }
74 } 109 }
75 } 110 }
111 }
76 112
77 Arc::new(res) 113 fn merge(&mut self, other: &Self) {
114 for (fp, impls) in &other.inherent_impls {
115 let vec = self.inherent_impls.entry(*fp).or_default();
116 vec.extend(impls);
117 vec.sort();
118 vec.dedup();
119 }
120
121 for (trait_, other_map) in &other.impls_by_trait {
122 let map = self.impls_by_trait.entry(*trait_).or_default();
123 for (fp, impls) in other_map {
124 let vec = map.entry(*fp).or_default();
125 vec.extend(impls);
126 vec.sort();
127 vec.dedup();
128 }
129 }
78 } 130 }
131
79 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 132 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
80 let fingerprint = TyFingerprint::for_impl(ty); 133 let fingerprint = TyFingerprint::for_impl(ty);
81 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 134 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
82 } 135 }
83 136
84 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { 137 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -110,7 +163,7 @@ impl CrateImplDefs {
110 } 163 }
111 164
112 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 165 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
113 self.impls 166 self.inherent_impls
114 .values() 167 .values()
115 .chain(self.impls_by_trait.values().flat_map(|m| m.values())) 168 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
116 .flatten() 169 .flatten()
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 1f004bd63..4da2e972b 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -633,3 +633,154 @@ where
633 "### 633 "###
634 ); 634 );
635} 635}
636
637#[test]
638fn issue_4953() {
639 assert_snapshot!(
640 infer(r#"
641pub struct Foo(pub i64);
642impl Foo {
643 fn test() -> Self { Self(0i64) }
644}
645"#),
646 @r###"
647 59..73 '{ Self(0i64) }': Foo
648 61..65 'Self': Foo(i64) -> Foo
649 61..71 'Self(0i64)': Foo
650 66..70 '0i64': i64
651 "###
652 );
653 assert_snapshot!(
654 infer(r#"
655pub struct Foo<T>(pub T);
656impl Foo<i64> {
657 fn test() -> Self { Self(0i64) }
658}
659"#),
660 @r###"
661 65..79 '{ Self(0i64) }': Foo<i64>
662 67..71 'Self': Foo<i64>(i64) -> Foo<i64>
663 67..77 'Self(0i64)': Foo<i64>
664 72..76 '0i64': i64
665 "###
666 );
667}
668
669#[test]
670fn issue_4931() {
671 assert_snapshot!(
672 infer(r#"
673trait Div<T> {
674 type Output;
675}
676
677trait CheckedDiv: Div<()> {}
678
679trait PrimInt: CheckedDiv<Output = ()> {
680 fn pow(self);
681}
682
683fn check<T: PrimInt>(i: T) {
684 i.pow();
685}
686"#),
687 @r###"
688 118..122 'self': Self
689 149..150 'i': T
690 155..171 '{ ...w(); }': ()
691 161..162 'i': T
692 161..168 'i.pow()': ()
693 "###
694 );
695}
696
697#[test]
698fn issue_4885() {
699 assert_snapshot!(
700 infer(r#"
701#[lang = "coerce_unsized"]
702pub trait CoerceUnsized<T> {}
703
704trait Future {
705 type Output;
706}
707trait Foo<R> {
708 type Bar;
709}
710fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar>
711where
712 K: Foo<R>,
713{
714 bar(key)
715}
716fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
717where
718 K: Foo<R>,
719{
720}
721"#),
722 @r###"
723 137..140 'key': &K
724 199..215 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
725 205..208 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
726 205..213 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
727 209..212 'key': &K
728 229..232 'key': &K
729 291..294 '{ }': ()
730 "###
731 );
732}
733
734#[test]
735fn issue_4800() {
736 assert_snapshot!(
737 infer(r#"
738trait Debug {}
739
740struct Foo<T>;
741
742type E1<T> = (T, T, T);
743type E2<T> = E1<E1<E1<(T, T, T)>>>;
744
745impl Debug for Foo<E2<()>> {}
746
747struct Request;
748
749pub trait Future {
750 type Output;
751}
752
753pub struct PeerSet<D>;
754
755impl<D> Service<Request> for PeerSet<D>
756where
757 D: Discover,
758 D::Key: Debug,
759{
760 type Error = ();
761 type Future = dyn Future<Output = Self::Error>;
762
763 fn call(&mut self) -> Self::Future {
764 loop {}
765 }
766}
767
768pub trait Discover {
769 type Key;
770}
771
772pub trait Service<Request> {
773 type Error;
774 type Future: Future<Output = Self::Error>;
775 fn call(&mut self) -> Self::Future;
776}
777"#),
778 @r###"
779 380..384 'self': &mut PeerSet<D>
780 402..425 '{ ... }': dyn Future<Output = ()>
781 412..419 'loop {}': !
782 417..419 '{}': ()
783 576..580 'self': &mut Self
784 "###
785 );
786}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e81193a3c..961be4abd 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2888,3 +2888,226 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
2888 ); 2888 );
2889 assert_eq!(t, "i32"); 2889 assert_eq!(t, "i32");
2890} 2890}
2891
2892#[test]
2893fn infer_closure_arg() {
2894 assert_snapshot!(
2895 infer(
2896 r#"
2897 //- /lib.rs
2898
2899 enum Option<T> {
2900 None,
2901 Some(T)
2902 }
2903
2904 fn foo() {
2905 let s = Option::None;
2906 let f = |x: Option<i32>| {};
2907 (&f)(s)
2908 }
2909 "#
2910 ),
2911 @r###"
2912 137..259 '{ ... }': ()
2913 159..160 's': Option<i32>
2914 163..175 'Option::None': Option<i32>
2915 197..198 'f': |Option<i32>| -> ()
2916 201..220 '|x: Op...2>| {}': |Option<i32>| -> ()
2917 202..203 'x': Option<i32>
2918 218..220 '{}': ()
2919 238..245 '(&f)(s)': ()
2920 239..241 '&f': &|Option<i32>| -> ()
2921 240..241 'f': |Option<i32>| -> ()
2922 243..244 's': Option<i32>
2923 "###
2924 );
2925}
2926
2927#[test]
2928fn infer_fn_trait_arg() {
2929 assert_snapshot!(
2930 infer(
2931 r#"
2932 //- /lib.rs deps:std
2933
2934 #[lang = "fn_once"]
2935 pub trait FnOnce<Args> {
2936 type Output;
2937
2938 extern "rust-call" fn call_once(&self, args: Args) -> Self::Output;
2939 }
2940
2941 #[lang = "fn"]
2942 pub trait Fn<Args>:FnOnce<Args> {
2943 extern "rust-call" fn call(&self, args: Args) -> Self::Output;
2944 }
2945
2946 enum Option<T> {
2947 None,
2948 Some(T)
2949 }
2950
2951 fn foo<F, T>(f: F) -> T
2952 where
2953 F: Fn(Option<i32>) -> T,
2954 {
2955 let s = None;
2956 f(s)
2957 }
2958 "#
2959 ),
2960 @r###"
2961 183..187 'self': &Self
2962 189..193 'args': Args
2963 350..354 'self': &Self
2964 356..360 'args': Args
2965 515..516 'f': F
2966 597..663 '{ ... }': T
2967 619..620 's': Option<i32>
2968 623..627 'None': Option<i32>
2969 645..646 'f': F
2970 645..649 'f(s)': T
2971 647..648 's': Option<i32>
2972 "###
2973 );
2974}
2975
2976#[test]
2977fn infer_box_fn_arg() {
2978 assert_snapshot!(
2979 infer(
2980 r#"
2981 //- /lib.rs deps:std
2982
2983 #[lang = "fn_once"]
2984 pub trait FnOnce<Args> {
2985 type Output;
2986
2987 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
2988 }
2989
2990 #[lang = "deref"]
2991 pub trait Deref {
2992 type Target: ?Sized;
2993
2994 fn deref(&self) -> &Self::Target;
2995 }
2996
2997 #[lang = "owned_box"]
2998 pub struct Box<T: ?Sized> {
2999 inner: *mut T,
3000 }
3001
3002 impl<T: ?Sized> Deref for Box<T> {
3003 type Target = T;
3004
3005 fn deref(&self) -> &T {
3006 &self.inner
3007 }
3008 }
3009
3010 enum Option<T> {
3011 None,
3012 Some(T)
3013 }
3014
3015 fn foo() {
3016 let s = Option::None;
3017 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3018 f(&s)
3019 }
3020 "#
3021 ),
3022 @r###"
3023 182..186 'self': Self
3024 188..192 'args': Args
3025 356..360 'self': &Self
3026 622..626 'self': &Box<T>
3027 634..685 '{ ... }': &T
3028 656..667 '&self.inner': &*mut T
3029 657..661 'self': &Box<T>
3030 657..667 'self.inner': *mut T
3031 812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
3032 834..835 's': Option<i32>
3033 838..850 'Option::None': Option<i32>
3034 872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>>
3035 907..920 'box (|ps| {})': Box<|{unknown}| -> ()>
3036 912..919 '|ps| {}': |{unknown}| -> ()
3037 913..915 'ps': {unknown}
3038 917..919 '{}': ()
3039 938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>>
3040 938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
3041 940..942 '&s': &Option<i32>
3042 941..942 's': Option<i32>
3043 "###
3044 );
3045}
3046
3047#[test]
3048fn infer_dyn_fn_output() {
3049 assert_snapshot!(
3050 infer(
3051 r#"
3052 //- /lib.rs deps:std
3053
3054 #[lang = "fn_once"]
3055 pub trait FnOnce<Args> {
3056 type Output;
3057
3058 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
3059 }
3060
3061 #[lang = "fn"]
3062 pub trait Fn<Args>:FnOnce<Args> {
3063 extern "rust-call" fn call(&self, args: Args) -> Self::Output;
3064 }
3065
3066 #[lang = "deref"]
3067 pub trait Deref {
3068 type Target: ?Sized;
3069
3070 fn deref(&self) -> &Self::Target;
3071 }
3072
3073 #[lang = "owned_box"]
3074 pub struct Box<T: ?Sized> {
3075 inner: *mut T,
3076 }
3077
3078 impl<T: ?Sized> Deref for Box<T> {
3079 type Target = T;
3080
3081 fn deref(&self) -> &T {
3082 &self.inner
3083 }
3084 }
3085
3086 fn foo() {
3087 let f: Box<dyn Fn() -> i32> = box(|| 5);
3088 let x = f();
3089 }
3090 "#
3091 ),
3092 @r###"
3093 182..186 'self': Self
3094 188..192 'args': Args
3095 349..353 'self': &Self
3096 355..359 'args': Args
3097 523..527 'self': &Self
3098 789..793 'self': &Box<T>
3099 801..852 '{ ... }': &T
3100 823..834 '&self.inner': &*mut T
3101 824..828 'self': &Box<T>
3102 824..834 'self.inner': *mut T
3103 889..990 '{ ... }': ()
3104 911..912 'f': Box<dyn Fn<(), Output = i32>>
3105 937..946 'box(|| 5)': Box<|| -> i32>
3106 941..945 '|| 5': || -> i32
3107 944..945 '5': i32
3108 968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
3109 972..973 'f': Box<dyn Fn<(), Output = i32>>
3110 972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
3111 "###
3112 );
3113}
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 6bc6d474c..6f43c3a22 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -2,12 +2,13 @@
2use std::{panic, sync::Arc}; 2use std::{panic, sync::Arc};
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; 5use hir_def::{
6 expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId,
7};
6use ra_db::{impl_intern_key, salsa, CrateId}; 8use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 9use ra_prof::profile;
8use rustc_hash::FxHashSet;
9 10
10use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex}; 11use crate::{db::HirDatabase, DebruijnIndex};
11 12
12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
13 14
@@ -36,34 +37,6 @@ fn create_chalk_solver() -> chalk_solve::Solver<Interner> {
36 solver_choice.into_solver() 37 solver_choice.into_solver()
37} 38}
38 39
39/// Collects impls for the given trait in the whole dependency tree of `krate`.
40pub(crate) fn impls_for_trait_query(
41 db: &dyn HirDatabase,
42 krate: CrateId,
43 trait_: TraitId,
44 self_ty_fp: Option<TyFingerprint>,
45) -> Arc<[ImplId]> {
46 // FIXME: We could be a lot smarter here - because of the orphan rules and
47 // the fact that the trait and the self type need to be in the dependency
48 // tree of a crate somewhere for an impl to exist, we could skip looking in
49 // a lot of crates completely
50 let mut impls = FxHashSet::default();
51 // We call the query recursively here. On the one hand, this means we can
52 // reuse results from queries for different crates; on the other hand, this
53 // will only ever get called for a few crates near the root of the tree (the
54 // ones the user is editing), so this may actually be a waste of memory. I'm
55 // doing it like this mainly for simplicity for now.
56 for dep in &db.crate_graph()[krate].dependencies {
57 impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter());
58 }
59 let crate_impl_defs = db.impls_in_crate(krate);
60 match self_ty_fp {
61 Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)),
62 None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)),
63 }
64 impls.into_iter().collect()
65}
66
67/// A set of clauses that we assume to be true. E.g. if we are inside this function: 40/// A set of clauses that we assume to be true. E.g. if we are inside this function:
68/// ```rust 41/// ```rust
69/// fn foo<T: Default>(t: T) {} 42/// fn foo<T: Default>(t: T) {}
@@ -298,6 +271,14 @@ impl FnTrait {
298 FnTrait::Fn => "fn", 271 FnTrait::Fn => "fn",
299 } 272 }
300 } 273 }
274
275 pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
276 let target = db.lang_item(krate, self.lang_item_name().into())?;
277 match target {
278 LangItemTarget::TraitId(t) => Some(t),
279 _ => None,
280 }
281 }
301} 282}
302 283
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 284#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 88a422d2c..6d5f2d46a 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -40,7 +40,7 @@ pub(super) fn get_builtin_impls(
40 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { 40 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
41 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() 41 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
42 { 42 {
43 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { 43 if let Some(actual_trait) = fn_trait.get_id(db, krate) {
44 if trait_ == actual_trait { 44 if trait_ == actual_trait {
45 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; 45 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
46 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { 46 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
@@ -128,7 +128,7 @@ fn check_closure_fn_trait_impl_prerequisites(
128 data: super::ClosureFnTraitImplData, 128 data: super::ClosureFnTraitImplData,
129) -> bool { 129) -> bool {
130 // the respective Fn/FnOnce/FnMut trait needs to exist 130 // the respective Fn/FnOnce/FnMut trait needs to exist
131 if get_fn_trait(db, krate, data.fn_trait).is_none() { 131 if data.fn_trait.get_id(db, krate).is_none() {
132 return false; 132 return false;
133 } 133 }
134 134
@@ -136,7 +136,7 @@ fn check_closure_fn_trait_impl_prerequisites(
136 // the traits having no type params, FnOnce being a supertrait 136 // the traits having no type params, FnOnce being a supertrait
137 137
138 // the FnOnce trait needs to exist and have an assoc type named Output 138 // the FnOnce trait needs to exist and have an assoc type named Output
139 let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) { 139 let fn_once_trait = match (super::FnTrait::FnOnce).get_id(db, krate) {
140 Some(t) => t, 140 Some(t) => t,
141 None => return false, 141 None => return false,
142 }; 142 };
@@ -151,7 +151,9 @@ fn closure_fn_trait_impl_datum(
151 // for some closure |X, Y| -> Z: 151 // for some closure |X, Y| -> Z:
152 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } 152 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
153 153
154 let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait 154 let trait_ = data
155 .fn_trait
156 .get_id(db, krate) // get corresponding fn trait
155 // the existence of the Fn trait has been checked before 157 // the existence of the Fn trait has been checked before
156 .expect("fn trait for closure impl missing"); 158 .expect("fn trait for closure impl missing");
157 159
@@ -211,7 +213,7 @@ fn closure_fn_trait_output_assoc_ty_value(
211 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into())); 213 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
212 214
213 let fn_once_trait = 215 let fn_once_trait =
214 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 216 (super::FnTrait::FnOnce).get_id(db, krate).expect("assoc ty value should not exist");
215 217
216 let output_ty_id = db 218 let output_ty_id = db
217 .trait_data(fn_once_trait) 219 .trait_data(fn_once_trait)
@@ -360,14 +362,6 @@ fn super_trait_object_unsize_impl_datum(
360 BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() } 362 BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() }
361} 363}
362 364
363fn get_fn_trait(db: &dyn HirDatabase, krate: CrateId, fn_trait: super::FnTrait) -> Option<TraitId> {
364 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
365 match target {
366 LangItemTarget::TraitId(t) => Some(t),
367 _ => None,
368 }
369}
370
371fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> { 365fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
372 let target = db.lang_item(krate, "unsize".into())?; 366 let target = db.lang_item(krate, "unsize".into())?;
373 match target { 367 match target {
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index a72a82f5a..2f35d6d49 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -74,14 +74,26 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
74 // Note: Since we're using impls_for_trait, only impls where the trait 74 // Note: Since we're using impls_for_trait, only impls where the trait
75 // can be resolved should ever reach Chalk. `impl_datum` relies on that 75 // can be resolved should ever reach Chalk. `impl_datum` relies on that
76 // and will panic if the trait can't be resolved. 76 // and will panic if the trait can't be resolved.
77 let mut result: Vec<_> = self 77 let in_deps = self.db.impls_from_deps(self.krate);
78 .db 78 let in_self = self.db.impls_in_crate(self.krate);
79 .impls_for_trait(self.krate, trait_, self_ty_fp) 79 let impl_maps = [in_deps, in_self];
80 .iter() 80
81 .copied() 81 let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
82 .map(Impl::ImplDef) 82
83 .map(|impl_| impl_.to_chalk(self.db)) 83 let mut result: Vec<_> = match self_ty_fp {
84 .collect(); 84 Some(fp) => impl_maps
85 .iter()
86 .flat_map(|crate_impl_defs| {
87 crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk)
88 })
89 .collect(),
90 None => impl_maps
91 .iter()
92 .flat_map(|crate_impl_defs| {
93 crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk)
94 })
95 .collect(),
96 };
85 97
86 let arg: Option<Ty> = 98 let arg: Option<Ty> =
87 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone())); 99 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index f98350bf9..c45820ff0 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -143,13 +143,14 @@ pub(super) fn find_super_trait_path(
143} 143}
144 144
145pub(super) fn associated_type_by_name_including_super_traits( 145pub(super) fn associated_type_by_name_including_super_traits(
146 db: &dyn DefDatabase, 146 db: &dyn HirDatabase,
147 trait_: TraitId, 147 trait_ref: TraitRef,
148 name: &Name, 148 name: &Name,
149) -> Option<TypeAliasId> { 149) -> Option<(TraitRef, TypeAliasId)> {
150 all_super_traits(db, trait_) 150 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
151 .into_iter() 151 let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
152 .find_map(|t| db.trait_data(t).associated_type_by_name(name)) 152 Some((t, assoc_type))
153 })
153} 154}
154 155
155pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> { 156pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
@@ -176,6 +177,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
176 Generics { def, params: db.generic_params(def), parent_generics } 177 Generics { def, params: db.generic_params(def), parent_generics }
177} 178}
178 179
180#[derive(Debug)]
179pub(crate) struct Generics { 181pub(crate) struct Generics {
180 def: GenericDefId, 182 def: GenericDefId,
181 pub(crate) params: Arc<GenericParams>, 183 pub(crate) params: Arc<GenericParams>,