diff options
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics/expr.rs | 169 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics/match_check.rs | 1561 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/test_db.rs | 23 |
4 files changed, 511 insertions, 1267 deletions
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 3623b8569..3016ca3bd 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -244,3 +244,28 @@ impl AstDiagnostic for MismatchedArgCount { | |||
244 | ast::CallExpr::cast(node).unwrap() | 244 | ast::CallExpr::cast(node).unwrap() |
245 | } | 245 | } |
246 | } | 246 | } |
247 | |||
248 | #[cfg(test)] | ||
249 | fn check_diagnostics(ra_fixture: &str) { | ||
250 | use ra_db::{fixture::WithFixture, FileId}; | ||
251 | use ra_syntax::TextRange; | ||
252 | use rustc_hash::FxHashMap; | ||
253 | |||
254 | use crate::test_db::TestDB; | ||
255 | |||
256 | let db = TestDB::with_files(ra_fixture); | ||
257 | let annotations = db.extract_annotations(); | ||
258 | |||
259 | let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default(); | ||
260 | db.diag(|d| { | ||
261 | // FXIME: macros... | ||
262 | let file_id = d.source().file_id.original_file(&db); | ||
263 | let range = d.syntax_node(&db).text_range(); | ||
264 | // FIXME: support multi-line messages in annotations | ||
265 | let message = d.message().lines().next().unwrap().to_owned(); | ||
266 | actual.entry(file_id).or_default().push((range, message)); | ||
267 | }); | ||
268 | actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start())); | ||
269 | |||
270 | assert_eq!(annotations, actual); | ||
271 | } | ||
diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs index 239be779f..277ace180 100644 --- a/crates/ra_hir_ty/src/diagnostics/expr.rs +++ b/crates/ra_hir_ty/src/diagnostics/expr.rs | |||
@@ -376,146 +376,117 @@ pub fn record_pattern_missing_fields( | |||
376 | 376 | ||
377 | #[cfg(test)] | 377 | #[cfg(test)] |
378 | mod tests { | 378 | mod tests { |
379 | use expect::{expect, Expect}; | 379 | use crate::diagnostics::check_diagnostics; |
380 | use ra_db::fixture::WithFixture; | ||
381 | |||
382 | use crate::{diagnostics::MismatchedArgCount, test_db::TestDB}; | ||
383 | |||
384 | fn check_diagnostic(ra_fixture: &str, expect: Expect) { | ||
385 | let msg = TestDB::with_single_file(ra_fixture).0.diagnostic::<MismatchedArgCount>().0; | ||
386 | expect.assert_eq(&msg); | ||
387 | } | ||
388 | |||
389 | fn check_no_diagnostic(ra_fixture: &str) { | ||
390 | let (s, diagnostic_count) = | ||
391 | TestDB::with_single_file(ra_fixture).0.diagnostic::<MismatchedArgCount>(); | ||
392 | |||
393 | assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s); | ||
394 | } | ||
395 | 380 | ||
396 | #[test] | 381 | #[test] |
397 | fn simple_free_fn_zero() { | 382 | fn simple_free_fn_zero() { |
398 | check_diagnostic( | 383 | check_diagnostics( |
399 | r" | 384 | r#" |
400 | fn zero() {} | 385 | fn zero() {} |
401 | fn f() { zero(1); } | 386 | fn f() { zero(1); } |
402 | ", | 387 | //^^^^^^^ Expected 0 arguments, found 1 |
403 | expect![["\"zero(1)\": Expected 0 arguments, found 1\n"]], | 388 | "#, |
404 | ); | 389 | ); |
405 | 390 | ||
406 | check_no_diagnostic( | 391 | check_diagnostics( |
407 | r" | 392 | r#" |
408 | fn zero() {} | 393 | fn zero() {} |
409 | fn f() { zero(); } | 394 | fn f() { zero(); } |
410 | ", | 395 | "#, |
411 | ); | 396 | ); |
412 | } | 397 | } |
413 | 398 | ||
414 | #[test] | 399 | #[test] |
415 | fn simple_free_fn_one() { | 400 | fn simple_free_fn_one() { |
416 | check_diagnostic( | 401 | check_diagnostics( |
417 | r" | 402 | r#" |
418 | fn one(arg: u8) {} | 403 | fn one(arg: u8) {} |
419 | fn f() { one(); } | 404 | fn f() { one(); } |
420 | ", | 405 | //^^^^^ Expected 1 argument, found 0 |
421 | expect![["\"one()\": Expected 1 argument, found 0\n"]], | 406 | "#, |
422 | ); | 407 | ); |
423 | 408 | ||
424 | check_no_diagnostic( | 409 | check_diagnostics( |
425 | r" | 410 | r#" |
426 | fn one(arg: u8) {} | 411 | fn one(arg: u8) {} |
427 | fn f() { one(1); } | 412 | fn f() { one(1); } |
428 | ", | 413 | "#, |
429 | ); | 414 | ); |
430 | } | 415 | } |
431 | 416 | ||
432 | #[test] | 417 | #[test] |
433 | fn method_as_fn() { | 418 | fn method_as_fn() { |
434 | check_diagnostic( | 419 | check_diagnostics( |
435 | r" | 420 | r#" |
436 | struct S; | 421 | struct S; |
437 | impl S { | 422 | impl S { fn method(&self) {} } |
438 | fn method(&self) {} | 423 | |
439 | } | 424 | fn f() { |
440 | 425 | S::method(); | |
441 | fn f() { | 426 | } //^^^^^^^^^^^ Expected 1 argument, found 0 |
442 | S::method(); | 427 | "#, |
443 | } | ||
444 | ", | ||
445 | expect![["\"S::method()\": Expected 1 argument, found 0\n"]], | ||
446 | ); | 428 | ); |
447 | 429 | ||
448 | check_no_diagnostic( | 430 | check_diagnostics( |
449 | r" | 431 | r#" |
450 | struct S; | 432 | struct S; |
451 | impl S { | 433 | impl S { fn method(&self) {} } |
452 | fn method(&self) {} | ||
453 | } | ||
454 | 434 | ||
455 | fn f() { | 435 | fn f() { |
456 | S::method(&S); | 436 | S::method(&S); |
457 | S.method(); | 437 | S.method(); |
458 | } | 438 | } |
459 | ", | 439 | "#, |
460 | ); | 440 | ); |
461 | } | 441 | } |
462 | 442 | ||
463 | #[test] | 443 | #[test] |
464 | fn method_with_arg() { | 444 | fn method_with_arg() { |
465 | check_diagnostic( | 445 | check_diagnostics( |
466 | r" | 446 | r#" |
467 | struct S; | 447 | struct S; |
468 | impl S { | 448 | impl S { fn method(&self, arg: u8) {} } |
469 | fn method(&self, arg: u8) {} | ||
470 | } | ||
471 | 449 | ||
472 | fn f() { | 450 | fn f() { |
473 | S.method(); | 451 | S.method(); |
474 | } | 452 | } //^^^^^^^^^^ Expected 1 argument, found 0 |
475 | ", | 453 | "#, |
476 | expect![["\"S.method()\": Expected 1 argument, found 0\n"]], | ||
477 | ); | 454 | ); |
478 | 455 | ||
479 | check_no_diagnostic( | 456 | check_diagnostics( |
480 | r" | 457 | r#" |
481 | struct S; | 458 | struct S; |
482 | impl S { | 459 | impl S { fn method(&self, arg: u8) {} } |
483 | fn method(&self, arg: u8) {} | ||
484 | } | ||
485 | 460 | ||
486 | fn f() { | 461 | fn f() { |
487 | S::method(&S, 0); | 462 | S::method(&S, 0); |
488 | S.method(1); | 463 | S.method(1); |
489 | } | 464 | } |
490 | ", | 465 | "#, |
491 | ); | 466 | ); |
492 | } | 467 | } |
493 | 468 | ||
494 | #[test] | 469 | #[test] |
495 | fn tuple_struct() { | 470 | fn tuple_struct() { |
496 | check_diagnostic( | 471 | check_diagnostics( |
497 | r" | 472 | r#" |
498 | struct Tup(u8, u16); | 473 | struct Tup(u8, u16); |
499 | fn f() { | 474 | fn f() { |
500 | Tup(0); | 475 | Tup(0); |
501 | } | 476 | } //^^^^^^ Expected 2 arguments, found 1 |
502 | ", | 477 | "#, |
503 | expect![["\"Tup(0)\": Expected 2 arguments, found 1\n"]], | ||
504 | ) | 478 | ) |
505 | } | 479 | } |
506 | 480 | ||
507 | #[test] | 481 | #[test] |
508 | fn enum_variant() { | 482 | fn enum_variant() { |
509 | check_diagnostic( | 483 | check_diagnostics( |
510 | r" | 484 | r#" |
511 | enum En { | 485 | enum En { Variant(u8, u16), } |
512 | Variant(u8, u16), | 486 | fn f() { |
513 | } | 487 | En::Variant(0); |
514 | fn f() { | 488 | } //^^^^^^^^^^^^^^ Expected 2 arguments, found 1 |
515 | En::Variant(0); | 489 | "#, |
516 | } | ||
517 | ", | ||
518 | expect![["\"En::Variant(0)\": Expected 2 arguments, found 1\n"]], | ||
519 | ) | 490 | ) |
520 | } | 491 | } |
521 | } | 492 | } |
diff --git a/crates/ra_hir_ty/src/diagnostics/match_check.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs index 899025a87..ba48b51b5 100644 --- a/crates/ra_hir_ty/src/diagnostics/match_check.rs +++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs | |||
@@ -41,9 +41,9 @@ | |||
41 | //! ```ignore | 41 | //! ```ignore |
42 | //! // x: (Option<bool>, Result<()>) | 42 | //! // x: (Option<bool>, Result<()>) |
43 | //! match x { | 43 | //! match x { |
44 | //! (Some(true), _) => {} | 44 | //! (Some(true), _) => (), |
45 | //! (None, Err(())) => {} | 45 | //! (None, Err(())) => (), |
46 | //! (None, Err(_)) => {} | 46 | //! (None, Err(_)) => (), |
47 | //! } | 47 | //! } |
48 | //! ``` | 48 | //! ``` |
49 | //! | 49 | //! |
@@ -837,685 +837,251 @@ fn enum_variant_matches(cx: &MatchCheckCtx, pat_id: PatId, enum_variant_id: Enum | |||
837 | 837 | ||
838 | #[cfg(test)] | 838 | #[cfg(test)] |
839 | mod tests { | 839 | mod tests { |
840 | use insta::assert_snapshot; | 840 | use crate::diagnostics::check_diagnostics; |
841 | use ra_db::fixture::WithFixture; | ||
842 | |||
843 | use crate::{diagnostics::MissingMatchArms, test_db::TestDB}; | ||
844 | |||
845 | fn check_diagnostic_message(ra_fixture: &str) -> String { | ||
846 | TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().0 | ||
847 | } | ||
848 | |||
849 | fn check_diagnostic(ra_fixture: &str) { | ||
850 | let diagnostic_count = | ||
851 | TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1; | ||
852 | |||
853 | assert_eq!(1, diagnostic_count, "no diagnostic reported"); | ||
854 | } | ||
855 | |||
856 | fn check_no_diagnostic(ra_fixture: &str) { | ||
857 | let (s, diagnostic_count) = | ||
858 | TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>(); | ||
859 | |||
860 | assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s); | ||
861 | } | ||
862 | |||
863 | #[test] | ||
864 | fn empty_tuple_no_arms_diagnostic_message() { | ||
865 | assert_snapshot!( | ||
866 | check_diagnostic_message(r" | ||
867 | fn test_fn() { | ||
868 | match () { | ||
869 | } | ||
870 | } | ||
871 | "), | ||
872 | @"\"()\": Missing match arm\n" | ||
873 | ); | ||
874 | } | ||
875 | |||
876 | #[test] | ||
877 | fn empty_tuple_no_arms() { | ||
878 | check_diagnostic( | ||
879 | r" | ||
880 | fn test_fn() { | ||
881 | match () { | ||
882 | } | ||
883 | } | ||
884 | ", | ||
885 | ); | ||
886 | } | ||
887 | |||
888 | #[test] | ||
889 | fn empty_tuple_wild() { | ||
890 | check_no_diagnostic( | ||
891 | r" | ||
892 | fn test_fn() { | ||
893 | match () { | ||
894 | _ => {} | ||
895 | } | ||
896 | } | ||
897 | ", | ||
898 | ); | ||
899 | } | ||
900 | 841 | ||
901 | #[test] | 842 | #[test] |
902 | fn empty_tuple_no_diagnostic() { | 843 | fn empty_tuple() { |
903 | check_no_diagnostic( | 844 | check_diagnostics( |
904 | r" | 845 | r#" |
905 | fn test_fn() { | 846 | fn main() { |
906 | match () { | 847 | match () { } |
907 | () => {} | 848 | //^^ Missing match arm |
908 | } | 849 | match (()) { } |
909 | } | 850 | //^^^^ Missing match arm |
910 | ", | ||
911 | ); | ||
912 | } | ||
913 | |||
914 | #[test] | ||
915 | fn tuple_of_empty_tuple_no_arms() { | ||
916 | check_diagnostic( | ||
917 | r" | ||
918 | fn test_fn() { | ||
919 | match (()) { | ||
920 | } | ||
921 | } | ||
922 | ", | ||
923 | ); | ||
924 | } | ||
925 | 851 | ||
926 | #[test] | 852 | match () { _ => (), } |
927 | fn tuple_of_empty_tuple_no_diagnostic() { | 853 | match () { () => (), } |
928 | check_no_diagnostic( | 854 | match (()) { (()) => (), } |
929 | r" | 855 | } |
930 | fn test_fn() { | 856 | "#, |
931 | match (()) { | ||
932 | (()) => {} | ||
933 | } | ||
934 | } | ||
935 | ", | ||
936 | ); | ||
937 | } | ||
938 | |||
939 | #[test] | ||
940 | fn tuple_of_two_empty_tuple_no_arms() { | ||
941 | check_diagnostic( | ||
942 | r" | ||
943 | fn test_fn() { | ||
944 | match ((), ()) { | ||
945 | } | ||
946 | } | ||
947 | ", | ||
948 | ); | ||
949 | } | ||
950 | |||
951 | #[test] | ||
952 | fn tuple_of_two_empty_tuple_no_diagnostic() { | ||
953 | check_no_diagnostic( | ||
954 | r" | ||
955 | fn test_fn() { | ||
956 | match ((), ()) { | ||
957 | ((), ()) => {} | ||
958 | } | ||
959 | } | ||
960 | ", | ||
961 | ); | ||
962 | } | ||
963 | |||
964 | #[test] | ||
965 | fn bool_no_arms() { | ||
966 | check_diagnostic( | ||
967 | r" | ||
968 | fn test_fn() { | ||
969 | match false { | ||
970 | } | ||
971 | } | ||
972 | ", | ||
973 | ); | ||
974 | } | ||
975 | |||
976 | #[test] | ||
977 | fn bool_missing_arm() { | ||
978 | check_diagnostic( | ||
979 | r" | ||
980 | fn test_fn() { | ||
981 | match false { | ||
982 | true => {} | ||
983 | } | ||
984 | } | ||
985 | ", | ||
986 | ); | ||
987 | } | ||
988 | |||
989 | #[test] | ||
990 | fn bool_no_diagnostic() { | ||
991 | check_no_diagnostic( | ||
992 | r" | ||
993 | fn test_fn() { | ||
994 | match false { | ||
995 | true => {} | ||
996 | false => {} | ||
997 | } | ||
998 | } | ||
999 | ", | ||
1000 | ); | ||
1001 | } | ||
1002 | |||
1003 | #[test] | ||
1004 | fn tuple_of_bools_no_arms() { | ||
1005 | check_diagnostic( | ||
1006 | r" | ||
1007 | fn test_fn() { | ||
1008 | match (false, true) { | ||
1009 | } | ||
1010 | } | ||
1011 | ", | ||
1012 | ); | ||
1013 | } | ||
1014 | |||
1015 | #[test] | ||
1016 | fn tuple_of_bools_missing_arms() { | ||
1017 | check_diagnostic( | ||
1018 | r" | ||
1019 | fn test_fn() { | ||
1020 | match (false, true) { | ||
1021 | (true, true) => {}, | ||
1022 | } | ||
1023 | } | ||
1024 | ", | ||
1025 | ); | ||
1026 | } | ||
1027 | |||
1028 | #[test] | ||
1029 | fn tuple_of_bools_missing_arm() { | ||
1030 | check_diagnostic( | ||
1031 | r" | ||
1032 | fn test_fn() { | ||
1033 | match (false, true) { | ||
1034 | (false, true) => {}, | ||
1035 | (false, false) => {}, | ||
1036 | (true, false) => {}, | ||
1037 | } | ||
1038 | } | ||
1039 | ", | ||
1040 | ); | ||
1041 | } | ||
1042 | |||
1043 | #[test] | ||
1044 | fn tuple_of_bools_with_wilds() { | ||
1045 | check_no_diagnostic( | ||
1046 | r" | ||
1047 | fn test_fn() { | ||
1048 | match (false, true) { | ||
1049 | (false, _) => {}, | ||
1050 | (true, false) => {}, | ||
1051 | (_, true) => {}, | ||
1052 | } | ||
1053 | } | ||
1054 | ", | ||
1055 | ); | 857 | ); |
1056 | } | 858 | } |
1057 | 859 | ||
1058 | #[test] | 860 | #[test] |
1059 | fn tuple_of_bools_no_diagnostic() { | 861 | fn tuple_of_two_empty_tuple() { |
1060 | check_no_diagnostic( | 862 | check_diagnostics( |
1061 | r" | 863 | r#" |
1062 | fn test_fn() { | 864 | fn main() { |
1063 | match (false, true) { | 865 | match ((), ()) { } |
1064 | (true, true) => {}, | 866 | //^^^^^^^^ Missing match arm |
1065 | (true, false) => {}, | ||
1066 | (false, true) => {}, | ||
1067 | (false, false) => {}, | ||
1068 | } | ||
1069 | } | ||
1070 | ", | ||
1071 | ); | ||
1072 | } | ||
1073 | 867 | ||
1074 | #[test] | 868 | match ((), ()) { ((), ()) => (), } |
1075 | fn tuple_of_bools_binding_missing_arms() { | 869 | } |
1076 | check_diagnostic( | 870 | "#, |
1077 | r" | 871 | ); |
1078 | fn test_fn() { | 872 | } |
1079 | match (false, true) { | 873 | |
1080 | (true, _x) => {}, | 874 | #[test] |
1081 | } | 875 | fn boolean() { |
1082 | } | 876 | check_diagnostics( |
1083 | ", | 877 | r#" |
1084 | ); | 878 | fn test_main() { |
1085 | } | 879 | match false { } |
1086 | 880 | //^^^^^ Missing match arm | |
1087 | #[test] | 881 | match false { true => (), } |
1088 | fn tuple_of_bools_binding_no_diagnostic() { | 882 | //^^^^^ Missing match arm |
1089 | check_no_diagnostic( | 883 | match (false, true) {} |
1090 | r" | 884 | //^^^^^^^^^^^^^ Missing match arm |
1091 | fn test_fn() { | 885 | match (false, true) { (true, true) => (), } |
1092 | match (false, true) { | 886 | //^^^^^^^^^^^^^ Missing match arm |
1093 | (true, _x) => {}, | 887 | match (false, true) { |
1094 | (false, true) => {}, | 888 | //^^^^^^^^^^^^^ Missing match arm |
1095 | (false, false) => {}, | 889 | (false, true) => (), |
1096 | } | 890 | (false, false) => (), |
1097 | } | 891 | (true, false) => (), |
1098 | ", | 892 | } |
893 | match (false, true) { (true, _x) => (), } | ||
894 | //^^^^^^^^^^^^^ Missing match arm | ||
895 | |||
896 | match false { true => (), false => (), } | ||
897 | match (false, true) { | ||
898 | (false, _) => (), | ||
899 | (true, false) => (), | ||
900 | (_, true) => (), | ||
901 | } | ||
902 | match (false, true) { | ||
903 | (true, true) => (), | ||
904 | (true, false) => (), | ||
905 | (false, true) => (), | ||
906 | (false, false) => (), | ||
907 | } | ||
908 | match (false, true) { | ||
909 | (true, _x) => (), | ||
910 | (false, true) => (), | ||
911 | (false, false) => (), | ||
912 | } | ||
913 | match (false, true, false) { | ||
914 | (false, ..) => (), | ||
915 | (true, ..) => (), | ||
916 | } | ||
917 | match (false, true, false) { | ||
918 | (.., false) => (), | ||
919 | (.., true) => (), | ||
920 | } | ||
921 | match (false, true, false) { (..) => (), } | ||
922 | } | ||
923 | "#, | ||
1099 | ); | 924 | ); |
1100 | } | 925 | } |
1101 | 926 | ||
1102 | #[test] | 927 | #[test] |
1103 | fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() { | 928 | fn tuple_of_tuple_and_bools() { |
1104 | check_no_diagnostic( | 929 | check_diagnostics( |
1105 | r" | 930 | r#" |
1106 | fn test_fn() { | 931 | fn main() { |
1107 | match (false, true, false) { | 932 | match (false, ((), false)) {} |
1108 | (false, ..) => {}, | 933 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
1109 | (true, ..) => {}, | 934 | match (false, ((), false)) { (true, ((), true)) => (), } |
1110 | } | 935 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
1111 | } | 936 | match (false, ((), false)) { (true, _) => (), } |
1112 | ", | 937 | //^^^^^^^^^^^^^^^^^^^^ Missing match arm |
1113 | ); | ||
1114 | } | ||
1115 | 938 | ||
1116 | #[test] | 939 | match (false, ((), false)) { |
1117 | fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() { | 940 | (true, ((), true)) => (), |
1118 | check_no_diagnostic( | 941 | (true, ((), false)) => (), |
1119 | r" | 942 | (false, ((), true)) => (), |
1120 | fn test_fn() { | 943 | (false, ((), false)) => (), |
1121 | match (false, true, false) { | ||
1122 | (.., false) => {}, | ||
1123 | (.., true) => {}, | ||
1124 | } | ||
1125 | } | ||
1126 | ", | ||
1127 | ); | ||
1128 | } | 944 | } |
1129 | 945 | match (false, ((), false)) { | |
1130 | #[test] | 946 | (true, ((), true)) => (), |
1131 | fn tuple_of_bools_with_ellipsis_no_diagnostic() { | 947 | (true, ((), false)) => (), |
1132 | check_no_diagnostic( | 948 | (false, _) => (), |
1133 | r" | ||
1134 | fn test_fn() { | ||
1135 | match (false, true, false) { | ||
1136 | (..) => {}, | ||
1137 | } | ||
1138 | } | ||
1139 | ", | ||
1140 | ); | ||
1141 | } | 949 | } |
1142 | 950 | } | |
1143 | #[test] | 951 | "#, |
1144 | fn tuple_of_tuple_and_bools_no_arms() { | ||
1145 | check_diagnostic( | ||
1146 | r" | ||
1147 | fn test_fn() { | ||
1148 | match (false, ((), false)) { | ||
1149 | } | ||
1150 | } | ||
1151 | ", | ||
1152 | ); | 952 | ); |
1153 | } | 953 | } |
1154 | 954 | ||
1155 | #[test] | 955 | #[test] |
1156 | fn tuple_of_tuple_and_bools_missing_arms() { | 956 | fn enums() { |
1157 | check_diagnostic( | 957 | check_diagnostics( |
1158 | r" | 958 | r#" |
1159 | fn test_fn() { | 959 | enum Either { A, B, } |
1160 | match (false, ((), false)) { | ||
1161 | (true, ((), true)) => {}, | ||
1162 | } | ||
1163 | } | ||
1164 | ", | ||
1165 | ); | ||
1166 | } | ||
1167 | 960 | ||
1168 | #[test] | 961 | fn main() { |
1169 | fn tuple_of_tuple_and_bools_no_diagnostic() { | 962 | match Either::A { } |
1170 | check_no_diagnostic( | 963 | //^^^^^^^^^ Missing match arm |
1171 | r" | 964 | match Either::B { Either::A => (), } |
1172 | fn test_fn() { | 965 | //^^^^^^^^^ Missing match arm |
1173 | match (false, ((), false)) { | ||
1174 | (true, ((), true)) => {}, | ||
1175 | (true, ((), false)) => {}, | ||
1176 | (false, ((), true)) => {}, | ||
1177 | (false, ((), false)) => {}, | ||
1178 | } | ||
1179 | } | ||
1180 | ", | ||
1181 | ); | ||
1182 | } | ||
1183 | 966 | ||
1184 | #[test] | 967 | match &Either::B { |
1185 | fn tuple_of_tuple_and_bools_wildcard_missing_arms() { | 968 | //^^^^^^^^^^ Missing match arm |
1186 | check_diagnostic( | 969 | Either::A => (), |
1187 | r" | ||
1188 | fn test_fn() { | ||
1189 | match (false, ((), false)) { | ||
1190 | (true, _) => {}, | ||
1191 | } | ||
1192 | } | ||
1193 | ", | ||
1194 | ); | ||
1195 | } | 970 | } |
1196 | 971 | ||
1197 | #[test] | 972 | match Either::B { |
1198 | fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() { | 973 | Either::A => (), Either::B => (), |
1199 | check_no_diagnostic( | ||
1200 | r" | ||
1201 | fn test_fn() { | ||
1202 | match (false, ((), false)) { | ||
1203 | (true, ((), true)) => {}, | ||
1204 | (true, ((), false)) => {}, | ||
1205 | (false, _) => {}, | ||
1206 | } | ||
1207 | } | ||
1208 | ", | ||
1209 | ); | ||
1210 | } | 974 | } |
1211 | 975 | match &Either::B { | |
1212 | #[test] | 976 | Either::A => (), Either::B => (), |
1213 | fn enum_no_arms() { | ||
1214 | check_diagnostic( | ||
1215 | r" | ||
1216 | enum Either { | ||
1217 | A, | ||
1218 | B, | ||
1219 | } | ||
1220 | fn test_fn() { | ||
1221 | match Either::A { | ||
1222 | } | ||
1223 | } | ||
1224 | ", | ||
1225 | ); | ||
1226 | } | 977 | } |
1227 | 978 | } | |
1228 | #[test] | 979 | "#, |
1229 | fn enum_missing_arms() { | ||
1230 | check_diagnostic( | ||
1231 | r" | ||
1232 | enum Either { | ||
1233 | A, | ||
1234 | B, | ||
1235 | } | ||
1236 | fn test_fn() { | ||
1237 | match Either::B { | ||
1238 | Either::A => {}, | ||
1239 | } | ||
1240 | } | ||
1241 | ", | ||
1242 | ); | 980 | ); |
1243 | } | 981 | } |
1244 | 982 | ||
1245 | #[test] | 983 | #[test] |
1246 | fn enum_no_diagnostic() { | 984 | fn enum_containing_bool() { |
1247 | check_no_diagnostic( | 985 | check_diagnostics( |
1248 | r" | 986 | r#" |
1249 | enum Either { | 987 | enum Either { A(bool), B } |
1250 | A, | ||
1251 | B, | ||
1252 | } | ||
1253 | fn test_fn() { | ||
1254 | match Either::B { | ||
1255 | Either::A => {}, | ||
1256 | Either::B => {}, | ||
1257 | } | ||
1258 | } | ||
1259 | ", | ||
1260 | ); | ||
1261 | } | ||
1262 | 988 | ||
1263 | #[test] | 989 | fn main() { |
1264 | fn enum_ref_missing_arms() { | 990 | match Either::B { } |
1265 | check_diagnostic( | 991 | //^^^^^^^^^ Missing match arm |
1266 | r" | 992 | match Either::B { |
1267 | enum Either { | 993 | //^^^^^^^^^ Missing match arm |
1268 | A, | 994 | Either::A(true) => (), Either::B => () |
1269 | B, | ||
1270 | } | ||
1271 | fn test_fn() { | ||
1272 | match &Either::B { | ||
1273 | Either::A => {}, | ||
1274 | } | ||
1275 | } | ||
1276 | ", | ||
1277 | ); | ||
1278 | } | 995 | } |
1279 | 996 | ||
1280 | #[test] | 997 | match Either::B { |
1281 | fn enum_ref_no_diagnostic() { | 998 | Either::A(true) => (), |
1282 | check_no_diagnostic( | 999 | Either::A(false) => (), |
1283 | r" | 1000 | Either::B => (), |
1284 | enum Either { | ||
1285 | A, | ||
1286 | B, | ||
1287 | } | ||
1288 | fn test_fn() { | ||
1289 | match &Either::B { | ||
1290 | Either::A => {}, | ||
1291 | Either::B => {}, | ||
1292 | } | ||
1293 | } | ||
1294 | ", | ||
1295 | ); | ||
1296 | } | 1001 | } |
1297 | 1002 | match Either::B { | |
1298 | #[test] | 1003 | Either::B => (), |
1299 | fn enum_containing_bool_no_arms() { | 1004 | _ => (), |
1300 | check_diagnostic( | ||
1301 | r" | ||
1302 | enum Either { | ||
1303 | A(bool), | ||
1304 | B, | ||
1305 | } | ||
1306 | fn test_fn() { | ||
1307 | match Either::B { | ||
1308 | } | ||
1309 | } | ||
1310 | ", | ||
1311 | ); | ||
1312 | } | 1005 | } |
1313 | 1006 | match Either::B { | |
1314 | #[test] | 1007 | Either::A(_) => (), |
1315 | fn enum_containing_bool_missing_arms() { | 1008 | Either::B => (), |
1316 | check_diagnostic( | ||
1317 | r" | ||
1318 | enum Either { | ||
1319 | A(bool), | ||
1320 | B, | ||
1321 | } | ||
1322 | fn test_fn() { | ||
1323 | match Either::B { | ||
1324 | Either::A(true) => (), | ||
1325 | Either::B => (), | ||
1326 | } | ||
1327 | } | ||
1328 | ", | ||
1329 | ); | ||
1330 | } | 1009 | } |
1331 | 1010 | ||
1332 | #[test] | 1011 | } |
1333 | fn enum_containing_bool_no_diagnostic() { | 1012 | "#, |
1334 | check_no_diagnostic( | ||
1335 | r" | ||
1336 | enum Either { | ||
1337 | A(bool), | ||
1338 | B, | ||
1339 | } | ||
1340 | fn test_fn() { | ||
1341 | match Either::B { | ||
1342 | Either::A(true) => (), | ||
1343 | Either::A(false) => (), | ||
1344 | Either::B => (), | ||
1345 | } | ||
1346 | } | ||
1347 | ", | ||
1348 | ); | 1013 | ); |
1349 | } | 1014 | } |
1350 | 1015 | ||
1351 | #[test] | 1016 | #[test] |
1352 | fn enum_containing_bool_with_wild_no_diagnostic() { | 1017 | fn enum_different_sizes() { |
1353 | check_no_diagnostic( | 1018 | check_diagnostics( |
1354 | r" | 1019 | r#" |
1355 | enum Either { | 1020 | enum Either { A(bool), B(bool, bool) } |
1356 | A(bool), | ||
1357 | B, | ||
1358 | } | ||
1359 | fn test_fn() { | ||
1360 | match Either::B { | ||
1361 | Either::B => (), | ||
1362 | _ => (), | ||
1363 | } | ||
1364 | } | ||
1365 | ", | ||
1366 | ); | ||
1367 | } | ||
1368 | 1021 | ||
1369 | #[test] | 1022 | fn main() { |
1370 | fn enum_containing_bool_with_wild_2_no_diagnostic() { | 1023 | match Either::A(false) { |
1371 | check_no_diagnostic( | 1024 | //^^^^^^^^^^^^^^^^ Missing match arm |
1372 | r" | 1025 | Either::A(_) => (), |
1373 | enum Either { | 1026 | Either::B(false, _) => (), |
1374 | A(bool), | ||
1375 | B, | ||
1376 | } | ||
1377 | fn test_fn() { | ||
1378 | match Either::B { | ||
1379 | Either::A(_) => (), | ||
1380 | Either::B => (), | ||
1381 | } | ||
1382 | } | ||
1383 | ", | ||
1384 | ); | ||
1385 | } | 1027 | } |
1386 | 1028 | ||
1387 | #[test] | 1029 | match Either::A(false) { |
1388 | fn enum_different_sizes_missing_arms() { | 1030 | Either::A(_) => (), |
1389 | check_diagnostic( | 1031 | Either::B(true, _) => (), |
1390 | r" | 1032 | Either::B(false, _) => (), |
1391 | enum Either { | ||
1392 | A(bool), | ||
1393 | B(bool, bool), | ||
1394 | } | ||
1395 | fn test_fn() { | ||
1396 | match Either::A(false) { | ||
1397 | Either::A(_) => (), | ||
1398 | Either::B(false, _) => (), | ||
1399 | } | ||
1400 | } | ||
1401 | ", | ||
1402 | ); | ||
1403 | } | 1033 | } |
1404 | 1034 | match Either::A(false) { | |
1405 | #[test] | 1035 | Either::A(true) | Either::A(false) => (), |
1406 | fn enum_different_sizes_no_diagnostic() { | 1036 | Either::B(true, _) => (), |
1407 | check_no_diagnostic( | 1037 | Either::B(false, _) => (), |
1408 | r" | ||
1409 | enum Either { | ||
1410 | A(bool), | ||
1411 | B(bool, bool), | ||
1412 | } | ||
1413 | fn test_fn() { | ||
1414 | match Either::A(false) { | ||
1415 | Either::A(_) => (), | ||
1416 | Either::B(true, _) => (), | ||
1417 | Either::B(false, _) => (), | ||
1418 | } | ||
1419 | } | ||
1420 | ", | ||
1421 | ); | ||
1422 | } | 1038 | } |
1423 | 1039 | } | |
1424 | #[test] | 1040 | "#, |
1425 | fn or_no_diagnostic() { | ||
1426 | check_no_diagnostic( | ||
1427 | r" | ||
1428 | enum Either { | ||
1429 | A(bool), | ||
1430 | B(bool, bool), | ||
1431 | } | ||
1432 | fn test_fn() { | ||
1433 | match Either::A(false) { | ||
1434 | Either::A(true) | Either::A(false) => (), | ||
1435 | Either::B(true, _) => (), | ||
1436 | Either::B(false, _) => (), | ||
1437 | } | ||
1438 | } | ||
1439 | ", | ||
1440 | ); | 1041 | ); |
1441 | } | 1042 | } |
1442 | 1043 | ||
1443 | #[test] | 1044 | #[test] |
1444 | fn tuple_of_enum_no_diagnostic() { | 1045 | fn tuple_of_enum_no_diagnostic() { |
1445 | check_no_diagnostic( | 1046 | check_diagnostics( |
1446 | r" | 1047 | r#" |
1447 | enum Either { | 1048 | enum Either { A(bool), B(bool, bool) } |
1448 | A(bool), | 1049 | enum Either2 { C, D } |
1449 | B(bool, bool), | 1050 | |
1450 | } | 1051 | fn main() { |
1451 | enum Either2 { | 1052 | match (Either::A(false), Either2::C) { |
1452 | C, | 1053 | (Either::A(true), _) | (Either::A(false), _) => (), |
1453 | D, | 1054 | (Either::B(true, _), Either2::C) => (), |
1454 | } | 1055 | (Either::B(false, _), Either2::C) => (), |
1455 | fn test_fn() { | 1056 | (Either::B(_, _), Either2::D) => (), |
1456 | match (Either::A(false), Either2::C) { | ||
1457 | (Either::A(true), _) | (Either::A(false), _) => (), | ||
1458 | (Either::B(true, _), Either2::C) => (), | ||
1459 | (Either::B(false, _), Either2::C) => (), | ||
1460 | (Either::B(_, _), Either2::D) => (), | ||
1461 | } | ||
1462 | } | ||
1463 | ", | ||
1464 | ); | ||
1465 | } | 1057 | } |
1466 | 1058 | } | |
1467 | #[test] | 1059 | "#, |
1468 | fn mismatched_types() { | ||
1469 | // Match statements with arms that don't match the | ||
1470 | // expression pattern do not fire this diagnostic. | ||
1471 | check_no_diagnostic( | ||
1472 | r" | ||
1473 | enum Either { | ||
1474 | A, | ||
1475 | B, | ||
1476 | } | ||
1477 | enum Either2 { | ||
1478 | C, | ||
1479 | D, | ||
1480 | } | ||
1481 | fn test_fn() { | ||
1482 | match Either::A { | ||
1483 | Either2::C => (), | ||
1484 | Either2::D => (), | ||
1485 | } | ||
1486 | } | ||
1487 | ", | ||
1488 | ); | ||
1489 | } | ||
1490 | |||
1491 | #[test] | ||
1492 | fn mismatched_types_with_different_arity() { | ||
1493 | // Match statements with arms that don't match the | ||
1494 | // expression pattern do not fire this diagnostic. | ||
1495 | check_no_diagnostic( | ||
1496 | r" | ||
1497 | fn test_fn() { | ||
1498 | match (true, false) { | ||
1499 | (true, false, true) => (), | ||
1500 | (true) => (), | ||
1501 | } | ||
1502 | } | ||
1503 | ", | ||
1504 | ); | 1060 | ); |
1505 | } | 1061 | } |
1506 | 1062 | ||
1507 | #[test] | 1063 | #[test] |
1508 | fn malformed_match_arm_tuple_missing_pattern() { | 1064 | fn mismatched_types() { |
1509 | // Match statements with arms that don't match the | 1065 | // Match statements with arms that don't match the |
1510 | // expression pattern do not fire this diagnostic. | 1066 | // expression pattern do not fire this diagnostic. |
1511 | check_no_diagnostic( | 1067 | check_diagnostics( |
1512 | r" | 1068 | r#" |
1513 | fn test_fn() { | 1069 | enum Either { A, B } |
1514 | match (0) { | 1070 | enum Either2 { C, D } |
1515 | () => (), | 1071 | |
1516 | } | 1072 | fn main() { |
1517 | } | 1073 | match Either::A { |
1518 | ", | 1074 | Either2::C => (), |
1075 | Either2::D => (), | ||
1076 | } | ||
1077 | match (true, false) { | ||
1078 | (true, false, true) => (), | ||
1079 | (true) => (), | ||
1080 | } | ||
1081 | match (0) { () => () } | ||
1082 | match Unresolved::Bar { Unresolved::Baz => () } | ||
1083 | } | ||
1084 | "#, | ||
1519 | ); | 1085 | ); |
1520 | } | 1086 | } |
1521 | 1087 | ||
@@ -1523,517 +1089,247 @@ mod tests { | |||
1523 | fn malformed_match_arm_tuple_enum_missing_pattern() { | 1089 | fn malformed_match_arm_tuple_enum_missing_pattern() { |
1524 | // We are testing to be sure we don't panic here when the match | 1090 | // We are testing to be sure we don't panic here when the match |
1525 | // arm `Either::B` is missing its pattern. | 1091 | // arm `Either::B` is missing its pattern. |
1526 | check_no_diagnostic( | 1092 | check_diagnostics( |
1527 | r" | 1093 | r#" |
1528 | enum Either { | 1094 | enum Either { A, B(u32) } |
1529 | A, | ||
1530 | B(u32), | ||
1531 | } | ||
1532 | fn test_fn() { | ||
1533 | match Either::A { | ||
1534 | Either::A => (), | ||
1535 | Either::B() => (), | ||
1536 | } | ||
1537 | } | ||
1538 | ", | ||
1539 | ); | ||
1540 | } | ||
1541 | 1095 | ||
1542 | #[test] | 1096 | fn main() { |
1543 | fn enum_not_in_scope() { | 1097 | match Either::A { |
1544 | // The enum is not in scope so we don't perform exhaustiveness | 1098 | Either::A => (), |
1545 | // checking, but we want to be sure we don't panic here (and | 1099 | Either::B() => (), |
1546 | // we don't create a diagnostic). | 1100 | } |
1547 | check_no_diagnostic( | 1101 | } |
1548 | r" | 1102 | "#, |
1549 | fn test_fn() { | ||
1550 | match Foo::Bar { | ||
1551 | Foo::Baz => (), | ||
1552 | } | ||
1553 | } | ||
1554 | ", | ||
1555 | ); | 1103 | ); |
1556 | } | 1104 | } |
1557 | 1105 | ||
1558 | #[test] | 1106 | #[test] |
1559 | fn expr_diverges() { | 1107 | fn expr_diverges() { |
1560 | check_no_diagnostic( | 1108 | check_diagnostics( |
1561 | r" | 1109 | r#" |
1562 | enum Either { | 1110 | enum Either { A, B } |
1563 | A, | ||
1564 | B, | ||
1565 | } | ||
1566 | fn test_fn() { | ||
1567 | match loop {} { | ||
1568 | Either::A => (), | ||
1569 | Either::B => (), | ||
1570 | } | ||
1571 | } | ||
1572 | ", | ||
1573 | ); | ||
1574 | } | ||
1575 | 1111 | ||
1576 | #[test] | 1112 | fn main() { |
1577 | fn expr_loop_with_break() { | 1113 | match loop {} { |
1578 | check_no_diagnostic( | 1114 | Either::A => (), |
1579 | r" | 1115 | Either::B => (), |
1580 | enum Either { | 1116 | } |
1581 | A, | 1117 | match loop {} { |
1582 | B, | 1118 | Either::A => (), |
1583 | } | 1119 | } |
1584 | fn test_fn() { | 1120 | match loop { break Foo::A } { |
1585 | match loop { break Foo::A } { | 1121 | //^^^^^^^^^^^^^^^^^^^^^ Missing match arm |
1586 | Either::A => (), | 1122 | Either::A => (), |
1587 | Either::B => (), | 1123 | } |
1588 | } | 1124 | match loop { break Foo::A } { |
1589 | } | 1125 | Either::A => (), |
1590 | ", | 1126 | Either::B => (), |
1127 | } | ||
1128 | } | ||
1129 | "#, | ||
1591 | ); | 1130 | ); |
1592 | } | 1131 | } |
1593 | 1132 | ||
1594 | #[test] | 1133 | #[test] |
1595 | fn expr_partially_diverges() { | 1134 | fn expr_partially_diverges() { |
1596 | check_no_diagnostic( | 1135 | check_diagnostics( |
1597 | r" | 1136 | r#" |
1598 | enum Either<T> { | 1137 | enum Either<T> { A(T), B } |
1599 | A(T), | ||
1600 | B, | ||
1601 | } | ||
1602 | fn foo() -> Either<!> { | ||
1603 | Either::B | ||
1604 | } | ||
1605 | fn test_fn() -> u32 { | ||
1606 | match foo() { | ||
1607 | Either::A(val) => val, | ||
1608 | Either::B => 0, | ||
1609 | } | ||
1610 | } | ||
1611 | ", | ||
1612 | ); | ||
1613 | } | ||
1614 | 1138 | ||
1615 | #[test] | 1139 | fn foo() -> Either<!> { Either::B } |
1616 | fn enum_record_no_arms() { | 1140 | fn main() -> u32 { |
1617 | check_diagnostic( | 1141 | match foo() { |
1618 | r" | 1142 | Either::A(val) => val, |
1619 | enum Either { | 1143 | Either::B => 0, |
1620 | A { foo: bool }, | ||
1621 | B, | ||
1622 | } | ||
1623 | fn test_fn() { | ||
1624 | let a = Either::A { foo: true }; | ||
1625 | match a { | ||
1626 | } | ||
1627 | } | ||
1628 | ", | ||
1629 | ); | ||
1630 | } | 1144 | } |
1631 | 1145 | } | |
1632 | #[test] | 1146 | "#, |
1633 | fn enum_record_missing_arms() { | ||
1634 | check_diagnostic( | ||
1635 | r" | ||
1636 | enum Either { | ||
1637 | A { foo: bool }, | ||
1638 | B, | ||
1639 | } | ||
1640 | fn test_fn() { | ||
1641 | let a = Either::A { foo: true }; | ||
1642 | match a { | ||
1643 | Either::A { foo: true } => (), | ||
1644 | } | ||
1645 | } | ||
1646 | ", | ||
1647 | ); | 1147 | ); |
1648 | } | 1148 | } |
1649 | 1149 | ||
1650 | #[test] | 1150 | #[test] |
1651 | fn enum_record_no_diagnostic() { | 1151 | fn enum_record() { |
1652 | check_no_diagnostic( | 1152 | check_diagnostics( |
1653 | r" | 1153 | r#" |
1654 | enum Either { | 1154 | enum Either { A { foo: bool }, B } |
1655 | A { foo: bool }, | ||
1656 | B, | ||
1657 | } | ||
1658 | fn test_fn() { | ||
1659 | let a = Either::A { foo: true }; | ||
1660 | match a { | ||
1661 | Either::A { foo: true } => (), | ||
1662 | Either::A { foo: false } => (), | ||
1663 | Either::B => (), | ||
1664 | } | ||
1665 | } | ||
1666 | ", | ||
1667 | ); | ||
1668 | } | ||
1669 | 1155 | ||
1670 | #[test] | 1156 | fn main() { |
1671 | fn enum_record_missing_field_no_diagnostic() { | 1157 | let a = Either::A { foo: true }; |
1672 | // When `Either::A` is missing a struct member, we don't want | 1158 | match a { } |
1673 | // to fire the missing match arm diagnostic. This should fire | 1159 | //^ Missing match arm |
1674 | // some other diagnostic. | 1160 | match a { Either::A { foo: true } => () } |
1675 | check_no_diagnostic( | 1161 | //^ Missing match arm |
1676 | r" | 1162 | match a { |
1677 | enum Either { | 1163 | Either::A { } => (), |
1678 | A { foo: bool }, | 1164 | //^^^ Missing structure fields: |
1679 | B, | 1165 | Either::B => (), |
1680 | } | ||
1681 | fn test_fn() { | ||
1682 | let a = Either::B; | ||
1683 | match a { | ||
1684 | Either::A { } => (), | ||
1685 | Either::B => (), | ||
1686 | } | ||
1687 | } | ||
1688 | ", | ||
1689 | ); | ||
1690 | } | 1166 | } |
1167 | match a { | ||
1168 | //^ Missing match arm | ||
1169 | Either::A { } => (), | ||
1170 | } //^^^ Missing structure fields: | ||
1691 | 1171 | ||
1692 | #[test] | 1172 | match a { |
1693 | fn enum_record_missing_field_missing_match_arm() { | 1173 | Either::A { foo: true } => (), |
1694 | // Even though `Either::A` is missing fields, we still want to fire | 1174 | Either::A { foo: false } => (), |
1695 | // the missing arm diagnostic here, since we know `Either::B` is missing. | 1175 | Either::B => (), |
1696 | check_diagnostic( | ||
1697 | r" | ||
1698 | enum Either { | ||
1699 | A { foo: bool }, | ||
1700 | B, | ||
1701 | } | ||
1702 | fn test_fn() { | ||
1703 | let a = Either::B; | ||
1704 | match a { | ||
1705 | Either::A { } => (), | ||
1706 | } | ||
1707 | } | ||
1708 | ", | ||
1709 | ); | ||
1710 | } | 1176 | } |
1711 | 1177 | match a { | |
1712 | #[test] | 1178 | Either::A { foo: _ } => (), |
1713 | fn enum_record_no_diagnostic_wild() { | 1179 | Either::B => (), |
1714 | check_no_diagnostic( | ||
1715 | r" | ||
1716 | enum Either { | ||
1717 | A { foo: bool }, | ||
1718 | B, | ||
1719 | } | ||
1720 | fn test_fn() { | ||
1721 | let a = Either::A { foo: true }; | ||
1722 | match a { | ||
1723 | Either::A { foo: _ } => (), | ||
1724 | Either::B => (), | ||
1725 | } | ||
1726 | } | ||
1727 | ", | ||
1728 | ); | ||
1729 | } | 1180 | } |
1730 | 1181 | } | |
1731 | #[test] | 1182 | "#, |
1732 | fn enum_record_fields_out_of_order_missing_arm() { | ||
1733 | check_diagnostic( | ||
1734 | r" | ||
1735 | enum Either { | ||
1736 | A { foo: bool, bar: () }, | ||
1737 | B, | ||
1738 | } | ||
1739 | fn test_fn() { | ||
1740 | let a = Either::A { foo: true }; | ||
1741 | match a { | ||
1742 | Either::A { bar: (), foo: false } => (), | ||
1743 | Either::A { foo: true, bar: () } => (), | ||
1744 | } | ||
1745 | } | ||
1746 | ", | ||
1747 | ); | 1183 | ); |
1748 | } | 1184 | } |
1749 | 1185 | ||
1750 | #[test] | 1186 | #[test] |
1751 | fn enum_record_fields_out_of_order_no_diagnostic() { | 1187 | fn enum_record_fields_out_of_order() { |
1752 | check_no_diagnostic( | 1188 | check_diagnostics( |
1753 | r" | 1189 | r#" |
1754 | enum Either { | 1190 | enum Either { |
1755 | A { foo: bool, bar: () }, | 1191 | A { foo: bool, bar: () }, |
1756 | B, | 1192 | B, |
1757 | } | 1193 | } |
1758 | fn test_fn() { | ||
1759 | let a = Either::A { foo: true }; | ||
1760 | match a { | ||
1761 | Either::A { bar: (), foo: false } => (), | ||
1762 | Either::A { foo: true, bar: () } => (), | ||
1763 | Either::B => (), | ||
1764 | } | ||
1765 | } | ||
1766 | ", | ||
1767 | ); | ||
1768 | } | ||
1769 | 1194 | ||
1770 | #[test] | 1195 | fn main() { |
1771 | fn enum_record_ellipsis_missing_arm() { | 1196 | let a = Either::A { foo: true, bar: () }; |
1772 | check_diagnostic( | 1197 | match a { |
1773 | r" | 1198 | //^ Missing match arm |
1774 | enum Either { | 1199 | Either::A { bar: (), foo: false } => (), |
1775 | A { foo: bool, bar: bool }, | 1200 | Either::A { foo: true, bar: () } => (), |
1776 | B, | ||
1777 | } | ||
1778 | fn test_fn() { | ||
1779 | match Either::B { | ||
1780 | Either::A { foo: true, .. } => (), | ||
1781 | Either::B => (), | ||
1782 | } | ||
1783 | } | ||
1784 | ", | ||
1785 | ); | ||
1786 | } | 1201 | } |
1787 | 1202 | ||
1788 | #[test] | 1203 | match a { |
1789 | fn enum_record_ellipsis_no_diagnostic() { | 1204 | Either::A { bar: (), foo: false } => (), |
1790 | check_no_diagnostic( | 1205 | Either::A { foo: true, bar: () } => (), |
1791 | r" | 1206 | Either::B => (), |
1792 | enum Either { | ||
1793 | A { foo: bool, bar: bool }, | ||
1794 | B, | ||
1795 | } | ||
1796 | fn test_fn() { | ||
1797 | let a = Either::A { foo: true }; | ||
1798 | match a { | ||
1799 | Either::A { foo: true, .. } => (), | ||
1800 | Either::A { foo: false, .. } => (), | ||
1801 | Either::B => (), | ||
1802 | } | ||
1803 | } | ||
1804 | ", | ||
1805 | ); | ||
1806 | } | 1207 | } |
1807 | 1208 | } | |
1808 | #[test] | 1209 | "#, |
1809 | fn enum_record_ellipsis_all_fields_missing_arm() { | ||
1810 | check_diagnostic( | ||
1811 | r" | ||
1812 | enum Either { | ||
1813 | A { foo: bool, bar: bool }, | ||
1814 | B, | ||
1815 | } | ||
1816 | fn test_fn() { | ||
1817 | let a = Either::B; | ||
1818 | match a { | ||
1819 | Either::A { .. } => (), | ||
1820 | } | ||
1821 | } | ||
1822 | ", | ||
1823 | ); | 1210 | ); |
1824 | } | 1211 | } |
1825 | 1212 | ||
1826 | #[test] | 1213 | #[test] |
1827 | fn enum_record_ellipsis_all_fields_no_diagnostic() { | 1214 | fn enum_record_ellipsis() { |
1828 | check_no_diagnostic( | 1215 | check_diagnostics( |
1829 | r" | 1216 | r#" |
1830 | enum Either { | 1217 | enum Either { |
1831 | A { foo: bool, bar: bool }, | 1218 | A { foo: bool, bar: bool }, |
1832 | B, | 1219 | B, |
1833 | } | 1220 | } |
1834 | fn test_fn() { | ||
1835 | let a = Either::B; | ||
1836 | match a { | ||
1837 | Either::A { .. } => (), | ||
1838 | Either::B => (), | ||
1839 | } | ||
1840 | } | ||
1841 | ", | ||
1842 | ); | ||
1843 | } | ||
1844 | 1221 | ||
1845 | #[test] | 1222 | fn main() { |
1846 | fn enum_tuple_partial_ellipsis_no_diagnostic() { | 1223 | let a = Either::B; |
1847 | check_no_diagnostic( | 1224 | match a { |
1848 | r" | 1225 | //^ Missing match arm |
1849 | enum Either { | 1226 | Either::A { foo: true, .. } => (), |
1850 | A(bool, bool, bool, bool), | 1227 | Either::B => (), |
1851 | B, | ||
1852 | } | ||
1853 | fn test_fn() { | ||
1854 | match Either::B { | ||
1855 | Either::A(true, .., true) => {}, | ||
1856 | Either::A(true, .., false) => {}, | ||
1857 | Either::A(false, .., true) => {}, | ||
1858 | Either::A(false, .., false) => {}, | ||
1859 | Either::B => {}, | ||
1860 | } | ||
1861 | } | ||
1862 | ", | ||
1863 | ); | ||
1864 | } | 1228 | } |
1865 | 1229 | match a { | |
1866 | #[test] | 1230 | //^ Missing match arm |
1867 | fn enum_tuple_partial_ellipsis_2_no_diagnostic() { | 1231 | Either::A { .. } => (), |
1868 | check_no_diagnostic( | ||
1869 | r" | ||
1870 | enum Either { | ||
1871 | A(bool, bool, bool, bool), | ||
1872 | B, | ||
1873 | } | ||
1874 | fn test_fn() { | ||
1875 | match Either::B { | ||
1876 | Either::A(true, .., true) => {}, | ||
1877 | Either::A(true, .., false) => {}, | ||
1878 | Either::A(.., true) => {}, | ||
1879 | Either::A(.., false) => {}, | ||
1880 | Either::B => {}, | ||
1881 | } | ||
1882 | } | ||
1883 | ", | ||
1884 | ); | ||
1885 | } | 1232 | } |
1886 | 1233 | ||
1887 | #[test] | 1234 | match a { |
1888 | fn enum_tuple_partial_ellipsis_missing_arm() { | 1235 | Either::A { foo: true, .. } => (), |
1889 | check_diagnostic( | 1236 | Either::A { foo: false, .. } => (), |
1890 | r" | 1237 | Either::B => (), |
1891 | enum Either { | ||
1892 | A(bool, bool, bool, bool), | ||
1893 | B, | ||
1894 | } | ||
1895 | fn test_fn() { | ||
1896 | match Either::B { | ||
1897 | Either::A(true, .., true) => {}, | ||
1898 | Either::A(true, .., false) => {}, | ||
1899 | Either::A(false, .., false) => {}, | ||
1900 | Either::B => {}, | ||
1901 | } | ||
1902 | } | ||
1903 | ", | ||
1904 | ); | ||
1905 | } | 1238 | } |
1906 | 1239 | ||
1907 | #[test] | 1240 | match a { |
1908 | fn enum_tuple_partial_ellipsis_2_missing_arm() { | 1241 | Either::A { .. } => (), |
1909 | check_diagnostic( | 1242 | Either::B => (), |
1910 | r" | ||
1911 | enum Either { | ||
1912 | A(bool, bool, bool, bool), | ||
1913 | B, | ||
1914 | } | ||
1915 | fn test_fn() { | ||
1916 | match Either::B { | ||
1917 | Either::A(true, .., true) => {}, | ||
1918 | Either::A(true, .., false) => {}, | ||
1919 | Either::A(.., true) => {}, | ||
1920 | Either::B => {}, | ||
1921 | } | ||
1922 | } | ||
1923 | ", | ||
1924 | ); | ||
1925 | } | 1243 | } |
1926 | 1244 | } | |
1927 | #[test] | 1245 | "#, |
1928 | fn enum_tuple_ellipsis_no_diagnostic() { | ||
1929 | check_no_diagnostic( | ||
1930 | r" | ||
1931 | enum Either { | ||
1932 | A(bool, bool, bool, bool), | ||
1933 | B, | ||
1934 | } | ||
1935 | fn test_fn() { | ||
1936 | match Either::B { | ||
1937 | Either::A(..) => {}, | ||
1938 | Either::B => {}, | ||
1939 | } | ||
1940 | } | ||
1941 | ", | ||
1942 | ); | 1246 | ); |
1943 | } | 1247 | } |
1944 | 1248 | ||
1945 | #[test] | 1249 | #[test] |
1946 | fn enum_never() { | 1250 | fn enum_tuple_partial_ellipsis() { |
1947 | check_no_diagnostic( | 1251 | check_diagnostics( |
1948 | r" | 1252 | r#" |
1949 | enum Never {} | 1253 | enum Either { |
1254 | A(bool, bool, bool, bool), | ||
1255 | B, | ||
1256 | } | ||
1950 | 1257 | ||
1951 | fn test_fn(never: Never) { | 1258 | fn main() { |
1952 | match never {} | 1259 | match Either::B { |
1953 | } | 1260 | //^^^^^^^^^ Missing match arm |
1954 | ", | 1261 | Either::A(true, .., true) => (), |
1955 | ); | 1262 | Either::A(true, .., false) => (), |
1263 | Either::A(false, .., false) => (), | ||
1264 | Either::B => (), | ||
1265 | } | ||
1266 | match Either::B { | ||
1267 | //^^^^^^^^^ Missing match arm | ||
1268 | Either::A(true, .., true) => (), | ||
1269 | Either::A(true, .., false) => (), | ||
1270 | Either::A(.., true) => (), | ||
1271 | Either::B => (), | ||
1272 | } | ||
1273 | |||
1274 | match Either::B { | ||
1275 | Either::A(true, .., true) => (), | ||
1276 | Either::A(true, .., false) => (), | ||
1277 | Either::A(false, .., true) => (), | ||
1278 | Either::A(false, .., false) => (), | ||
1279 | Either::B => (), | ||
1280 | } | ||
1281 | match Either::B { | ||
1282 | Either::A(true, .., true) => (), | ||
1283 | Either::A(true, .., false) => (), | ||
1284 | Either::A(.., true) => (), | ||
1285 | Either::A(.., false) => (), | ||
1286 | Either::B => (), | ||
1956 | } | 1287 | } |
1957 | 1288 | } | |
1958 | #[test] | 1289 | "#, |
1959 | fn type_never() { | ||
1960 | check_no_diagnostic( | ||
1961 | r" | ||
1962 | fn test_fn(never: !) { | ||
1963 | match never {} | ||
1964 | } | ||
1965 | ", | ||
1966 | ); | 1290 | ); |
1967 | } | 1291 | } |
1968 | 1292 | ||
1969 | #[test] | 1293 | #[test] |
1970 | fn enum_never_ref() { | 1294 | fn never() { |
1971 | check_no_diagnostic( | 1295 | check_diagnostics( |
1972 | r" | 1296 | r#" |
1973 | enum Never {} | 1297 | enum Never {} |
1974 | 1298 | ||
1975 | fn test_fn(never: &Never) { | 1299 | fn enum_(never: Never) { |
1976 | match never {} | 1300 | match never {} |
1977 | } | 1301 | } |
1978 | ", | 1302 | fn enum_ref(never: &Never) { |
1979 | ); | 1303 | match never {} |
1980 | } | 1304 | } |
1981 | 1305 | fn bang(never: !) { | |
1982 | #[test] | 1306 | match never {} |
1983 | fn expr_diverges_missing_arm() { | 1307 | } |
1984 | check_no_diagnostic( | 1308 | "#, |
1985 | r" | ||
1986 | enum Either { | ||
1987 | A, | ||
1988 | B, | ||
1989 | } | ||
1990 | fn test_fn() { | ||
1991 | match loop {} { | ||
1992 | Either::A => (), | ||
1993 | } | ||
1994 | } | ||
1995 | ", | ||
1996 | ); | 1309 | ); |
1997 | } | 1310 | } |
1998 | 1311 | ||
1999 | #[test] | 1312 | #[test] |
2000 | fn or_pattern_panic() { | 1313 | fn or_pattern_panic() { |
2001 | check_no_diagnostic( | 1314 | check_diagnostics( |
2002 | r" | 1315 | r#" |
2003 | pub enum Category { | 1316 | pub enum Category { Infinity, Zero } |
2004 | Infinity, | ||
2005 | Zero, | ||
2006 | } | ||
2007 | 1317 | ||
2008 | fn panic(a: Category, b: Category) { | 1318 | fn panic(a: Category, b: Category) { |
2009 | match (a, b) { | 1319 | match (a, b) { |
2010 | (Category::Zero | Category::Infinity, _) => {} | 1320 | (Category::Zero | Category::Infinity, _) => (), |
2011 | (_, Category::Zero | Category::Infinity) => {} | 1321 | (_, Category::Zero | Category::Infinity) => (), |
2012 | } | ||
2013 | } | ||
2014 | ", | ||
2015 | ); | ||
2016 | } | 1322 | } |
2017 | 1323 | ||
2018 | #[test] | 1324 | // FIXME: This is a false positive, but the code used to cause a panic in the match checker, |
2019 | fn or_pattern_panic_2() { | 1325 | // so this acts as a regression test for that. |
2020 | // FIXME: This is a false positive, but the code used to cause a panic in the match checker, | 1326 | match (a, b) { |
2021 | // so this acts as a regression test for that. | 1327 | //^^^^^^ Missing match arm |
2022 | check_diagnostic( | 1328 | (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (), |
2023 | r" | 1329 | (Category::Infinity | Category::Zero, _) => (), |
2024 | pub enum Category { | 1330 | } |
2025 | Infinity, | 1331 | } |
2026 | Zero, | 1332 | "#, |
2027 | } | ||
2028 | |||
2029 | fn panic(a: Category, b: Category) { | ||
2030 | match (a, b) { | ||
2031 | (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {} | ||
2032 | |||
2033 | (Category::Infinity | Category::Zero, _) => {} | ||
2034 | } | ||
2035 | } | ||
2036 | ", | ||
2037 | ); | 1333 | ); |
2038 | } | 1334 | } |
2039 | 1335 | ||
@@ -2051,105 +1347,72 @@ mod tests { | |||
2051 | 1347 | ||
2052 | #[test] | 1348 | #[test] |
2053 | fn integers() { | 1349 | fn integers() { |
2054 | // This is a false negative. | ||
2055 | // We don't currently check integer exhaustiveness. | 1350 | // We don't currently check integer exhaustiveness. |
2056 | check_no_diagnostic( | 1351 | check_diagnostics( |
2057 | r" | 1352 | r#" |
2058 | fn test_fn() { | 1353 | fn main() { |
2059 | match 5 { | 1354 | match 5 { |
2060 | 10 => (), | 1355 | 10 => (), |
2061 | 11..20 => (), | 1356 | 11..20 => (), |
2062 | } | 1357 | } |
2063 | } | 1358 | } |
2064 | ", | 1359 | "#, |
2065 | ); | 1360 | ); |
2066 | } | 1361 | } |
2067 | 1362 | ||
2068 | #[test] | 1363 | #[test] |
2069 | fn internal_or() { | 1364 | fn internal_or() { |
2070 | // This is a false negative. | ||
2071 | // We do not currently handle patterns with internal `or`s. | 1365 | // We do not currently handle patterns with internal `or`s. |
2072 | check_no_diagnostic( | 1366 | check_diagnostics( |
2073 | r" | 1367 | r#" |
2074 | fn test_fn() { | 1368 | fn main() { |
2075 | enum Either { | 1369 | enum Either { A(bool), B } |
2076 | A(bool), | 1370 | match Either::B { |
2077 | B, | 1371 | Either::A(true | false) => (), |
2078 | } | 1372 | } |
2079 | match Either::B { | 1373 | } |
2080 | Either::A(true | false) => (), | 1374 | "#, |
2081 | } | ||
2082 | } | ||
2083 | ", | ||
2084 | ); | ||
2085 | } | ||
2086 | |||
2087 | #[test] | ||
2088 | fn expr_loop_missing_arm() { | ||
2089 | // This is a false negative. | ||
2090 | // We currently infer the type of `loop { break Foo::A }` to `!`, which | ||
2091 | // causes us to skip the diagnostic since `Either::A` doesn't type check | ||
2092 | // with `!`. | ||
2093 | check_diagnostic( | ||
2094 | r" | ||
2095 | enum Either { | ||
2096 | A, | ||
2097 | B, | ||
2098 | } | ||
2099 | fn test_fn() { | ||
2100 | match loop { break Foo::A } { | ||
2101 | Either::A => (), | ||
2102 | } | ||
2103 | } | ||
2104 | ", | ||
2105 | ); | 1375 | ); |
2106 | } | 1376 | } |
2107 | 1377 | ||
2108 | #[test] | 1378 | #[test] |
2109 | fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { | 1379 | fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { |
2110 | // This is a false negative. | ||
2111 | // We don't currently handle tuple patterns with ellipsis. | 1380 | // We don't currently handle tuple patterns with ellipsis. |
2112 | check_no_diagnostic( | 1381 | check_diagnostics( |
2113 | r" | 1382 | r#" |
2114 | fn test_fn() { | 1383 | fn main() { |
2115 | match (false, true, false) { | 1384 | match (false, true, false) { |
2116 | (false, ..) => {}, | 1385 | (false, ..) => (), |
2117 | } | 1386 | } |
2118 | } | 1387 | } |
2119 | ", | 1388 | "#, |
2120 | ); | 1389 | ); |
2121 | } | 1390 | } |
2122 | 1391 | ||
2123 | #[test] | 1392 | #[test] |
2124 | fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { | 1393 | fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { |
2125 | // This is a false negative. | ||
2126 | // We don't currently handle tuple patterns with ellipsis. | 1394 | // We don't currently handle tuple patterns with ellipsis. |
2127 | check_no_diagnostic( | 1395 | check_diagnostics( |
2128 | r" | 1396 | r#" |
2129 | fn test_fn() { | 1397 | fn main() { |
2130 | match (false, true, false) { | 1398 | match (false, true, false) { |
2131 | (.., false) => {}, | 1399 | (.., false) => (), |
2132 | } | 1400 | } |
2133 | } | 1401 | } |
2134 | ", | 1402 | "#, |
2135 | ); | 1403 | ); |
2136 | } | 1404 | } |
2137 | 1405 | ||
2138 | #[test] | 1406 | #[test] |
2139 | fn struct_missing_arm() { | 1407 | fn struct_missing_arm() { |
2140 | // This is a false negative. | ||
2141 | // We don't currently handle structs. | 1408 | // We don't currently handle structs. |
2142 | check_no_diagnostic( | 1409 | check_diagnostics( |
2143 | r" | 1410 | r#" |
2144 | struct Foo { | 1411 | struct Foo { a: bool } |
2145 | a: bool, | 1412 | fn main(f: Foo) { |
2146 | } | 1413 | match f { Foo { a: true } => () } |
2147 | fn test_fn(f: Foo) { | 1414 | } |
2148 | match f { | 1415 | "#, |
2149 | Foo { a: true } => {}, | ||
2150 | } | ||
2151 | } | ||
2152 | ", | ||
2153 | ); | 1416 | ); |
2154 | } | 1417 | } |
2155 | } | 1418 | } |
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index ddafd0ea1..fb8723fb7 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs | |||
@@ -82,7 +82,7 @@ impl FileLoader for TestDB { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | impl TestDB { | 84 | impl TestDB { |
85 | pub fn module_for_file(&self, file_id: FileId) -> ModuleId { | 85 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { |
86 | for &krate in self.relevant_crates(file_id).iter() { | 86 | for &krate in self.relevant_crates(file_id).iter() { |
87 | let crate_def_map = self.crate_def_map(krate); | 87 | let crate_def_map = self.crate_def_map(krate); |
88 | for (local_id, data) in crate_def_map.modules.iter() { | 88 | for (local_id, data) in crate_def_map.modules.iter() { |
@@ -94,7 +94,7 @@ impl TestDB { | |||
94 | panic!("Can't find module for file") | 94 | panic!("Can't find module for file") |
95 | } | 95 | } |
96 | 96 | ||
97 | fn diag<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) { | 97 | pub(crate) fn diag<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) { |
98 | let crate_graph = self.crate_graph(); | 98 | let crate_graph = self.crate_graph(); |
99 | for krate in crate_graph.iter() { | 99 | for krate in crate_graph.iter() { |
100 | let crate_def_map = self.crate_def_map(krate); | 100 | let crate_def_map = self.crate_def_map(krate); |
@@ -124,7 +124,7 @@ impl TestDB { | |||
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | pub fn diagnostics(&self) -> (String, u32) { | 127 | pub(crate) fn diagnostics(&self) -> (String, u32) { |
128 | let mut buf = String::new(); | 128 | let mut buf = String::new(); |
129 | let mut count = 0; | 129 | let mut count = 0; |
130 | self.diag(|d| { | 130 | self.diag(|d| { |
@@ -134,22 +134,7 @@ impl TestDB { | |||
134 | (buf, count) | 134 | (buf, count) |
135 | } | 135 | } |
136 | 136 | ||
137 | /// Like `diagnostics`, but filtered for a single diagnostic. | 137 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { |
138 | pub fn diagnostic<D: Diagnostic>(&self) -> (String, u32) { | ||
139 | let mut buf = String::new(); | ||
140 | let mut count = 0; | ||
141 | self.diag(|d| { | ||
142 | // We want to filter diagnostics by the particular one we are testing for, to | ||
143 | // avoid surprising results in tests. | ||
144 | if d.downcast_ref::<D>().is_some() { | ||
145 | format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
146 | count += 1; | ||
147 | }; | ||
148 | }); | ||
149 | (buf, count) | ||
150 | } | ||
151 | |||
152 | pub fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { | ||
153 | let mut files = Vec::new(); | 138 | let mut files = Vec::new(); |
154 | let crate_graph = self.crate_graph(); | 139 | let crate_graph = self.crate_graph(); |
155 | for krate in crate_graph.iter() { | 140 | for krate in crate_graph.iter() { |