aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-06-12 17:28:19 +0100
committerAleksey Kladov <[email protected]>2021-06-12 19:00:22 +0100
commit6940cfed1e24a67e816e69e1093e04c0eb73e070 (patch)
tree68825f63dc6bdb571498ba659a2cf57bd31accb4 /crates/ide/src
parent6f0141a14026827edfe4ef046013001acd22d94d (diff)
Move some hir_ty diagnostics to hir
Diffstat (limited to 'crates/ide/src')
-rw-r--r--crates/ide/src/diagnostics.rs1304
1 files changed, 1303 insertions, 1 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index b791747c2..dffb6fdc8 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -204,8 +204,9 @@ pub(crate) fn diagnostics(
204 ); 204 );
205 }); 205 });
206 206
207 let internal_diagnostics = cfg!(test);
207 match sema.to_module_def(file_id) { 208 match sema.to_module_def(file_id) {
208 Some(m) => m.diagnostics(db, &mut sink), 209 Some(m) => m.diagnostics(db, &mut sink, internal_diagnostics),
209 None => { 210 None => {
210 sink.push(UnlinkedFile { file_id, node: SyntaxNodePtr::new(&parse.tree().syntax()) }); 211 sink.push(UnlinkedFile { file_id, node: SyntaxNodePtr::new(&parse.tree().syntax()) });
211 } 212 }
@@ -942,4 +943,1305 @@ fn main() {
942"#, 943"#,
943 ); 944 );
944 } 945 }
946
947 // Register the required standard library types to make the tests work
948 fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
949 let prefix = r#"
950 //- /main.rs crate:main deps:core
951 use core::iter::Iterator;
952 use core::option::Option::{self, Some, None};
953 "#;
954 let suffix = r#"
955 //- /core/lib.rs crate:core
956 pub mod option {
957 pub enum Option<T> { Some(T), None }
958 }
959 pub mod iter {
960 pub trait Iterator {
961 type Item;
962 fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap }
963 fn next(&mut self) -> Option<Self::Item>;
964 }
965 pub struct FilterMap {}
966 impl Iterator for FilterMap {
967 type Item = i32;
968 fn next(&mut self) -> i32 { 7 }
969 }
970 }
971 "#;
972 format!("{}{}{}", prefix, body, suffix)
973 }
974
975 #[test]
976 fn replace_filter_map_next_with_find_map2() {
977 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
978 r#"
979 fn foo() {
980 let m = [1, 2, 3].iter().filter_map(|x| if *x == 2 { Some (4) } else { None }).next();
981 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ replace filter_map(..).next() with find_map(..)
982 }
983 "#,
984 ));
985 }
986
987 #[test]
988 fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
989 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
990 r#"
991 fn foo() {
992 let m = [1, 2, 3]
993 .iter()
994 .filter_map(|x| if *x == 2 { Some (4) } else { None })
995 .len();
996 }
997 "#,
998 ));
999 }
1000
1001 #[test]
1002 fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() {
1003 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
1004 r#"
1005 fn foo() {
1006 let m = [1, 2, 3]
1007 .iter()
1008 .filter_map(|x| if *x == 2 { Some (4) } else { None })
1009 .map(|x| x + 2)
1010 .len();
1011 }
1012 "#,
1013 ));
1014 }
1015
1016 #[test]
1017 fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() {
1018 check_diagnostics(&add_filter_map_with_find_next_boilerplate(
1019 r#"
1020 fn foo() {
1021 let m = [1, 2, 3]
1022 .iter()
1023 .filter_map(|x| if *x == 2 { Some (4) } else { None });
1024 let n = m.next();
1025 }
1026 "#,
1027 ));
1028 }
1029
1030 #[test]
1031 fn missing_record_pat_field_diagnostic() {
1032 check_diagnostics(
1033 r#"
1034struct S { foo: i32, bar: () }
1035fn baz(s: S) {
1036 let S { foo: _ } = s;
1037 //^ Missing structure fields:
1038 //| - bar
1039}
1040"#,
1041 );
1042 }
1043
1044 #[test]
1045 fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
1046 check_diagnostics(
1047 r"
1048struct S { foo: i32, bar: () }
1049fn baz(s: S) -> i32 {
1050 match s {
1051 S { foo, .. } => foo,
1052 }
1053}
1054",
1055 )
1056 }
1057
1058 #[test]
1059 fn missing_record_pat_field_box() {
1060 check_diagnostics(
1061 r"
1062struct S { s: Box<u32> }
1063fn x(a: S) {
1064 let S { box s } = a;
1065}
1066",
1067 )
1068 }
1069
1070 #[test]
1071 fn missing_record_pat_field_ref() {
1072 check_diagnostics(
1073 r"
1074struct S { s: u32 }
1075fn x(a: S) {
1076 let S { ref s } = a;
1077}
1078",
1079 )
1080 }
1081
1082 #[test]
1083 fn simple_free_fn_zero() {
1084 check_diagnostics(
1085 r#"
1086fn zero() {}
1087fn f() { zero(1); }
1088 //^^^^^^^ Expected 0 arguments, found 1
1089"#,
1090 );
1091
1092 check_diagnostics(
1093 r#"
1094fn zero() {}
1095fn f() { zero(); }
1096"#,
1097 );
1098 }
1099
1100 #[test]
1101 fn simple_free_fn_one() {
1102 check_diagnostics(
1103 r#"
1104fn one(arg: u8) {}
1105fn f() { one(); }
1106 //^^^^^ Expected 1 argument, found 0
1107"#,
1108 );
1109
1110 check_diagnostics(
1111 r#"
1112fn one(arg: u8) {}
1113fn f() { one(1); }
1114"#,
1115 );
1116 }
1117
1118 #[test]
1119 fn method_as_fn() {
1120 check_diagnostics(
1121 r#"
1122struct S;
1123impl S { fn method(&self) {} }
1124
1125fn f() {
1126 S::method();
1127} //^^^^^^^^^^^ Expected 1 argument, found 0
1128"#,
1129 );
1130
1131 check_diagnostics(
1132 r#"
1133struct S;
1134impl S { fn method(&self) {} }
1135
1136fn f() {
1137 S::method(&S);
1138 S.method();
1139}
1140"#,
1141 );
1142 }
1143
1144 #[test]
1145 fn method_with_arg() {
1146 check_diagnostics(
1147 r#"
1148struct S;
1149impl S { fn method(&self, arg: u8) {} }
1150
1151 fn f() {
1152 S.method();
1153 } //^^^^^^^^^^ Expected 1 argument, found 0
1154 "#,
1155 );
1156
1157 check_diagnostics(
1158 r#"
1159struct S;
1160impl S { fn method(&self, arg: u8) {} }
1161
1162fn f() {
1163 S::method(&S, 0);
1164 S.method(1);
1165}
1166"#,
1167 );
1168 }
1169
1170 #[test]
1171 fn method_unknown_receiver() {
1172 // note: this is incorrect code, so there might be errors on this in the
1173 // future, but we shouldn't emit an argument count diagnostic here
1174 check_diagnostics(
1175 r#"
1176trait Foo { fn method(&self, arg: usize) {} }
1177
1178fn f() {
1179 let x;
1180 x.method();
1181}
1182"#,
1183 );
1184 }
1185
1186 #[test]
1187 fn tuple_struct() {
1188 check_diagnostics(
1189 r#"
1190struct Tup(u8, u16);
1191fn f() {
1192 Tup(0);
1193} //^^^^^^ Expected 2 arguments, found 1
1194"#,
1195 )
1196 }
1197
1198 #[test]
1199 fn enum_variant() {
1200 check_diagnostics(
1201 r#"
1202enum En { Variant(u8, u16), }
1203fn f() {
1204 En::Variant(0);
1205} //^^^^^^^^^^^^^^ Expected 2 arguments, found 1
1206"#,
1207 )
1208 }
1209
1210 #[test]
1211 fn enum_variant_type_macro() {
1212 check_diagnostics(
1213 r#"
1214macro_rules! Type {
1215 () => { u32 };
1216}
1217enum Foo {
1218 Bar(Type![])
1219}
1220impl Foo {
1221 fn new() {
1222 Foo::Bar(0);
1223 Foo::Bar(0, 1);
1224 //^^^^^^^^^^^^^^ Expected 1 argument, found 2
1225 Foo::Bar();
1226 //^^^^^^^^^^ Expected 1 argument, found 0
1227 }
1228}
1229 "#,
1230 );
1231 }
1232
1233 #[test]
1234 fn varargs() {
1235 check_diagnostics(
1236 r#"
1237extern "C" {
1238 fn fixed(fixed: u8);
1239 fn varargs(fixed: u8, ...);
1240 fn varargs2(...);
1241}
1242
1243fn f() {
1244 unsafe {
1245 fixed(0);
1246 fixed(0, 1);
1247 //^^^^^^^^^^^ Expected 1 argument, found 2
1248 varargs(0);
1249 varargs(0, 1);
1250 varargs2();
1251 varargs2(0);
1252 varargs2(0, 1);
1253 }
1254}
1255 "#,
1256 )
1257 }
1258
1259 #[test]
1260 fn arg_count_lambda() {
1261 check_diagnostics(
1262 r#"
1263fn main() {
1264 let f = |()| ();
1265 f();
1266 //^^^ Expected 1 argument, found 0
1267 f(());
1268 f((), ());
1269 //^^^^^^^^^ Expected 1 argument, found 2
1270}
1271"#,
1272 )
1273 }
1274
1275 #[test]
1276 fn cfgd_out_call_arguments() {
1277 check_diagnostics(
1278 r#"
1279struct C(#[cfg(FALSE)] ());
1280impl C {
1281 fn new() -> Self {
1282 Self(
1283 #[cfg(FALSE)]
1284 (),
1285 )
1286 }
1287
1288 fn method(&self) {}
1289}
1290
1291fn main() {
1292 C::new().method(#[cfg(FALSE)] 0);
1293}
1294 "#,
1295 );
1296 }
1297
1298 #[test]
1299 fn cfgd_out_fn_params() {
1300 check_diagnostics(
1301 r#"
1302fn foo(#[cfg(NEVER)] x: ()) {}
1303
1304struct S;
1305
1306impl S {
1307 fn method(#[cfg(NEVER)] self) {}
1308 fn method2(#[cfg(NEVER)] self, arg: u8) {}
1309 fn method3(self, #[cfg(NEVER)] arg: u8) {}
1310}
1311
1312extern "C" {
1313 fn fixed(fixed: u8, #[cfg(NEVER)] ...);
1314 fn varargs(#[cfg(not(NEVER))] ...);
1315}
1316
1317fn main() {
1318 foo();
1319 S::method();
1320 S::method2(0);
1321 S::method3(S);
1322 S.method3();
1323 unsafe {
1324 fixed(0);
1325 varargs(1, 2, 3);
1326 }
1327}
1328 "#,
1329 )
1330 }
1331
1332 #[test]
1333 fn missing_semicolon() {
1334 check_diagnostics(
1335 r#"
1336 fn test() -> i32 { 123; }
1337 //^^^ Remove this semicolon
1338 "#,
1339 );
1340 }
1341}
1342
1343#[cfg(test)]
1344pub(super) mod match_check_tests {
1345 use crate::diagnostics::tests::check_diagnostics;
1346
1347 #[test]
1348 fn empty_tuple() {
1349 check_diagnostics(
1350 r#"
1351fn main() {
1352 match () { }
1353 //^^ Missing match arm
1354 match (()) { }
1355 //^^^^ Missing match arm
1356
1357 match () { _ => (), }
1358 match () { () => (), }
1359 match (()) { (()) => (), }
1360}
1361"#,
1362 );
1363 }
1364
1365 #[test]
1366 fn tuple_of_two_empty_tuple() {
1367 check_diagnostics(
1368 r#"
1369fn main() {
1370 match ((), ()) { }
1371 //^^^^^^^^ Missing match arm
1372
1373 match ((), ()) { ((), ()) => (), }
1374}
1375"#,
1376 );
1377 }
1378
1379 #[test]
1380 fn boolean() {
1381 check_diagnostics(
1382 r#"
1383fn test_main() {
1384 match false { }
1385 //^^^^^ Missing match arm
1386 match false { true => (), }
1387 //^^^^^ Missing match arm
1388 match (false, true) {}
1389 //^^^^^^^^^^^^^ Missing match arm
1390 match (false, true) { (true, true) => (), }
1391 //^^^^^^^^^^^^^ Missing match arm
1392 match (false, true) {
1393 //^^^^^^^^^^^^^ Missing match arm
1394 (false, true) => (),
1395 (false, false) => (),
1396 (true, false) => (),
1397 }
1398 match (false, true) { (true, _x) => (), }
1399 //^^^^^^^^^^^^^ Missing match arm
1400
1401 match false { true => (), false => (), }
1402 match (false, true) {
1403 (false, _) => (),
1404 (true, false) => (),
1405 (_, true) => (),
1406 }
1407 match (false, true) {
1408 (true, true) => (),
1409 (true, false) => (),
1410 (false, true) => (),
1411 (false, false) => (),
1412 }
1413 match (false, true) {
1414 (true, _x) => (),
1415 (false, true) => (),
1416 (false, false) => (),
1417 }
1418 match (false, true, false) {
1419 (false, ..) => (),
1420 (true, ..) => (),
1421 }
1422 match (false, true, false) {
1423 (.., false) => (),
1424 (.., true) => (),
1425 }
1426 match (false, true, false) { (..) => (), }
1427}
1428"#,
1429 );
1430 }
1431
1432 #[test]
1433 fn tuple_of_tuple_and_bools() {
1434 check_diagnostics(
1435 r#"
1436fn main() {
1437 match (false, ((), false)) {}
1438 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1439 match (false, ((), false)) { (true, ((), true)) => (), }
1440 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1441 match (false, ((), false)) { (true, _) => (), }
1442 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1443
1444 match (false, ((), false)) {
1445 (true, ((), true)) => (),
1446 (true, ((), false)) => (),
1447 (false, ((), true)) => (),
1448 (false, ((), false)) => (),
1449 }
1450 match (false, ((), false)) {
1451 (true, ((), true)) => (),
1452 (true, ((), false)) => (),
1453 (false, _) => (),
1454 }
1455}
1456"#,
1457 );
1458 }
1459
1460 #[test]
1461 fn enums() {
1462 check_diagnostics(
1463 r#"
1464enum Either { A, B, }
1465
1466fn main() {
1467 match Either::A { }
1468 //^^^^^^^^^ Missing match arm
1469 match Either::B { Either::A => (), }
1470 //^^^^^^^^^ Missing match arm
1471
1472 match &Either::B {
1473 //^^^^^^^^^^ Missing match arm
1474 Either::A => (),
1475 }
1476
1477 match Either::B {
1478 Either::A => (), Either::B => (),
1479 }
1480 match &Either::B {
1481 Either::A => (), Either::B => (),
1482 }
1483}
1484"#,
1485 );
1486 }
1487
1488 #[test]
1489 fn enum_containing_bool() {
1490 check_diagnostics(
1491 r#"
1492enum Either { A(bool), B }
1493
1494fn main() {
1495 match Either::B { }
1496 //^^^^^^^^^ Missing match arm
1497 match Either::B {
1498 //^^^^^^^^^ Missing match arm
1499 Either::A(true) => (), Either::B => ()
1500 }
1501
1502 match Either::B {
1503 Either::A(true) => (),
1504 Either::A(false) => (),
1505 Either::B => (),
1506 }
1507 match Either::B {
1508 Either::B => (),
1509 _ => (),
1510 }
1511 match Either::B {
1512 Either::A(_) => (),
1513 Either::B => (),
1514 }
1515
1516}
1517 "#,
1518 );
1519 }
1520
1521 #[test]
1522 fn enum_different_sizes() {
1523 check_diagnostics(
1524 r#"
1525enum Either { A(bool), B(bool, bool) }
1526
1527fn main() {
1528 match Either::A(false) {
1529 //^^^^^^^^^^^^^^^^ Missing match arm
1530 Either::A(_) => (),
1531 Either::B(false, _) => (),
1532 }
1533
1534 match Either::A(false) {
1535 Either::A(_) => (),
1536 Either::B(true, _) => (),
1537 Either::B(false, _) => (),
1538 }
1539 match Either::A(false) {
1540 Either::A(true) | Either::A(false) => (),
1541 Either::B(true, _) => (),
1542 Either::B(false, _) => (),
1543 }
1544}
1545"#,
1546 );
1547 }
1548
1549 #[test]
1550 fn tuple_of_enum_no_diagnostic() {
1551 check_diagnostics(
1552 r#"
1553enum Either { A(bool), B(bool, bool) }
1554enum Either2 { C, D }
1555
1556fn main() {
1557 match (Either::A(false), Either2::C) {
1558 (Either::A(true), _) | (Either::A(false), _) => (),
1559 (Either::B(true, _), Either2::C) => (),
1560 (Either::B(false, _), Either2::C) => (),
1561 (Either::B(_, _), Either2::D) => (),
1562 }
1563}
1564"#,
1565 );
1566 }
1567
1568 #[test]
1569 fn or_pattern_no_diagnostic() {
1570 check_diagnostics(
1571 r#"
1572enum Either {A, B}
1573
1574fn main() {
1575 match (Either::A, Either::B) {
1576 (Either::A | Either::B, _) => (),
1577 }
1578}"#,
1579 )
1580 }
1581
1582 #[test]
1583 fn mismatched_types() {
1584 // Match statements with arms that don't match the
1585 // expression pattern do not fire this diagnostic.
1586 check_diagnostics(
1587 r#"
1588enum Either { A, B }
1589enum Either2 { C, D }
1590
1591fn main() {
1592 match Either::A {
1593 Either2::C => (),
1594 // ^^^^^^^^^^ Internal: match check bailed out
1595 Either2::D => (),
1596 }
1597 match (true, false) {
1598 (true, false, true) => (),
1599 // ^^^^^^^^^^^^^^^^^^^ Internal: match check bailed out
1600 (true) => (),
1601 }
1602 match (true, false) { (true,) => {} }
1603 // ^^^^^^^ Internal: match check bailed out
1604 match (0) { () => () }
1605 // ^^ Internal: match check bailed out
1606 match Unresolved::Bar { Unresolved::Baz => () }
1607}
1608 "#,
1609 );
1610 }
1611
1612 #[test]
1613 fn mismatched_types_in_or_patterns() {
1614 check_diagnostics(
1615 r#"
1616fn main() {
1617 match false { true | () => {} }
1618 // ^^^^^^^^^ Internal: match check bailed out
1619 match (false,) { (true | (),) => {} }
1620 // ^^^^^^^^^^^^ Internal: match check bailed out
1621}
1622"#,
1623 );
1624 }
1625
1626 #[test]
1627 fn malformed_match_arm_tuple_enum_missing_pattern() {
1628 // We are testing to be sure we don't panic here when the match
1629 // arm `Either::B` is missing its pattern.
1630 check_diagnostics(
1631 r#"
1632enum Either { A, B(u32) }
1633
1634fn main() {
1635 match Either::A {
1636 Either::A => (),
1637 Either::B() => (),
1638 }
1639}
1640"#,
1641 );
1642 }
1643
1644 #[test]
1645 fn malformed_match_arm_extra_fields() {
1646 check_diagnostics(
1647 r#"
1648enum A { B(isize, isize), C }
1649fn main() {
1650 match A::B(1, 2) {
1651 A::B(_, _, _) => (),
1652 // ^^^^^^^^^^^^^ Internal: match check bailed out
1653 }
1654 match A::B(1, 2) {
1655 A::C(_) => (),
1656 // ^^^^^^^ Internal: match check bailed out
1657 }
1658}
1659"#,
1660 );
1661 }
1662
1663 #[test]
1664 fn expr_diverges() {
1665 check_diagnostics(
1666 r#"
1667enum Either { A, B }
1668
1669fn main() {
1670 match loop {} {
1671 Either::A => (),
1672 // ^^^^^^^^^ Internal: match check bailed out
1673 Either::B => (),
1674 }
1675 match loop {} {
1676 Either::A => (),
1677 // ^^^^^^^^^ Internal: match check bailed out
1678 }
1679 match loop { break Foo::A } {
1680 //^^^^^^^^^^^^^^^^^^^^^ Missing match arm
1681 Either::A => (),
1682 }
1683 match loop { break Foo::A } {
1684 Either::A => (),
1685 Either::B => (),
1686 }
1687}
1688"#,
1689 );
1690 }
1691
1692 #[test]
1693 fn expr_partially_diverges() {
1694 check_diagnostics(
1695 r#"
1696enum Either<T> { A(T), B }
1697
1698fn foo() -> Either<!> { Either::B }
1699fn main() -> u32 {
1700 match foo() {
1701 Either::A(val) => val,
1702 Either::B => 0,
1703 }
1704}
1705"#,
1706 );
1707 }
1708
1709 #[test]
1710 fn enum_record() {
1711 check_diagnostics(
1712 r#"
1713enum Either { A { foo: bool }, B }
1714
1715fn main() {
1716 let a = Either::A { foo: true };
1717 match a { }
1718 //^ Missing match arm
1719 match a { Either::A { foo: true } => () }
1720 //^ Missing match arm
1721 match a {
1722 Either::A { } => (),
1723 //^^^^^^^^^ Missing structure fields:
1724 // | - foo
1725 Either::B => (),
1726 }
1727 match a {
1728 //^ Missing match arm
1729 Either::A { } => (),
1730 } //^^^^^^^^^ Missing structure fields:
1731 // | - foo
1732
1733 match a {
1734 Either::A { foo: true } => (),
1735 Either::A { foo: false } => (),
1736 Either::B => (),
1737 }
1738 match a {
1739 Either::A { foo: _ } => (),
1740 Either::B => (),
1741 }
1742}
1743"#,
1744 );
1745 }
1746
1747 #[test]
1748 fn enum_record_fields_out_of_order() {
1749 check_diagnostics(
1750 r#"
1751enum Either {
1752 A { foo: bool, bar: () },
1753 B,
1754}
1755
1756fn main() {
1757 let a = Either::A { foo: true, bar: () };
1758 match a {
1759 //^ Missing match arm
1760 Either::A { bar: (), foo: false } => (),
1761 Either::A { foo: true, bar: () } => (),
1762 }
1763
1764 match a {
1765 Either::A { bar: (), foo: false } => (),
1766 Either::A { foo: true, bar: () } => (),
1767 Either::B => (),
1768 }
1769}
1770"#,
1771 );
1772 }
1773
1774 #[test]
1775 fn enum_record_ellipsis() {
1776 check_diagnostics(
1777 r#"
1778enum Either {
1779 A { foo: bool, bar: bool },
1780 B,
1781}
1782
1783fn main() {
1784 let a = Either::B;
1785 match a {
1786 //^ Missing match arm
1787 Either::A { foo: true, .. } => (),
1788 Either::B => (),
1789 }
1790 match a {
1791 //^ Missing match arm
1792 Either::A { .. } => (),
1793 }
1794
1795 match a {
1796 Either::A { foo: true, .. } => (),
1797 Either::A { foo: false, .. } => (),
1798 Either::B => (),
1799 }
1800
1801 match a {
1802 Either::A { .. } => (),
1803 Either::B => (),
1804 }
1805}
1806"#,
1807 );
1808 }
1809
1810 #[test]
1811 fn enum_tuple_partial_ellipsis() {
1812 check_diagnostics(
1813 r#"
1814enum Either {
1815 A(bool, bool, bool, bool),
1816 B,
1817}
1818
1819fn main() {
1820 match Either::B {
1821 //^^^^^^^^^ Missing match arm
1822 Either::A(true, .., true) => (),
1823 Either::A(true, .., false) => (),
1824 Either::A(false, .., false) => (),
1825 Either::B => (),
1826 }
1827 match Either::B {
1828 //^^^^^^^^^ Missing match arm
1829 Either::A(true, .., true) => (),
1830 Either::A(true, .., false) => (),
1831 Either::A(.., true) => (),
1832 Either::B => (),
1833 }
1834
1835 match Either::B {
1836 Either::A(true, .., true) => (),
1837 Either::A(true, .., false) => (),
1838 Either::A(false, .., true) => (),
1839 Either::A(false, .., false) => (),
1840 Either::B => (),
1841 }
1842 match Either::B {
1843 Either::A(true, .., true) => (),
1844 Either::A(true, .., false) => (),
1845 Either::A(.., true) => (),
1846 Either::A(.., false) => (),
1847 Either::B => (),
1848 }
1849}
1850"#,
1851 );
1852 }
1853
1854 #[test]
1855 fn never() {
1856 check_diagnostics(
1857 r#"
1858enum Never {}
1859
1860fn enum_(never: Never) {
1861 match never {}
1862}
1863fn enum_ref(never: &Never) {
1864 match never {}
1865 //^^^^^ Missing match arm
1866}
1867fn bang(never: !) {
1868 match never {}
1869}
1870"#,
1871 );
1872 }
1873
1874 #[test]
1875 fn unknown_type() {
1876 check_diagnostics(
1877 r#"
1878enum Option<T> { Some(T), None }
1879
1880fn main() {
1881 // `Never` is deliberately not defined so that it's an uninferred type.
1882 match Option::<Never>::None {
1883 None => (),
1884 Some(never) => match never {},
1885 // ^^^^^^^^^^^ Internal: match check bailed out
1886 }
1887 match Option::<Never>::None {
1888 //^^^^^^^^^^^^^^^^^^^^^ Missing match arm
1889 Option::Some(_never) => {},
1890 }
1891}
1892"#,
1893 );
1894 }
1895
1896 #[test]
1897 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
1898 check_diagnostics(
1899 r#"
1900fn main() {
1901 match (false, true, false) {
1902 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1903 (false, ..) => (),
1904 }
1905}"#,
1906 );
1907 }
1908
1909 #[test]
1910 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() {
1911 check_diagnostics(
1912 r#"
1913fn main() {
1914 match (false, true, false) {
1915 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1916 (.., false) => (),
1917 }
1918}"#,
1919 );
1920 }
1921
1922 #[test]
1923 fn tuple_of_bools_with_ellipsis_in_middle_missing_arm() {
1924 check_diagnostics(
1925 r#"
1926fn main() {
1927 match (false, true, false) {
1928 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1929 (true, .., false) => (),
1930 }
1931}"#,
1932 );
1933 }
1934
1935 #[test]
1936 fn record_struct() {
1937 check_diagnostics(
1938 r#"struct Foo { a: bool }
1939fn main(f: Foo) {
1940 match f {}
1941 //^ Missing match arm
1942 match f { Foo { a: true } => () }
1943 //^ Missing match arm
1944 match &f { Foo { a: true } => () }
1945 //^^ Missing match arm
1946 match f { Foo { a: _ } => () }
1947 match f {
1948 Foo { a: true } => (),
1949 Foo { a: false } => (),
1950 }
1951 match &f {
1952 Foo { a: true } => (),
1953 Foo { a: false } => (),
1954 }
1955}
1956"#,
1957 );
1958 }
1959
1960 #[test]
1961 fn tuple_struct() {
1962 check_diagnostics(
1963 r#"struct Foo(bool);
1964fn main(f: Foo) {
1965 match f {}
1966 //^ Missing match arm
1967 match f { Foo(true) => () }
1968 //^ Missing match arm
1969 match f {
1970 Foo(true) => (),
1971 Foo(false) => (),
1972 }
1973}
1974"#,
1975 );
1976 }
1977
1978 #[test]
1979 fn unit_struct() {
1980 check_diagnostics(
1981 r#"struct Foo;
1982fn main(f: Foo) {
1983 match f {}
1984 //^ Missing match arm
1985 match f { Foo => () }
1986}
1987"#,
1988 );
1989 }
1990
1991 #[test]
1992 fn record_struct_ellipsis() {
1993 check_diagnostics(
1994 r#"struct Foo { foo: bool, bar: bool }
1995fn main(f: Foo) {
1996 match f { Foo { foo: true, .. } => () }
1997 //^ Missing match arm
1998 match f {
1999 //^ Missing match arm
2000 Foo { foo: true, .. } => (),
2001 Foo { bar: false, .. } => ()
2002 }
2003 match f { Foo { .. } => () }
2004 match f {
2005 Foo { foo: true, .. } => (),
2006 Foo { foo: false, .. } => ()
2007 }
2008}
2009"#,
2010 );
2011 }
2012
2013 #[test]
2014 fn internal_or() {
2015 check_diagnostics(
2016 r#"
2017fn main() {
2018 enum Either { A(bool), B }
2019 match Either::B {
2020 //^^^^^^^^^ Missing match arm
2021 Either::A(true | false) => (),
2022 }
2023}
2024"#,
2025 );
2026 }
2027
2028 #[test]
2029 fn no_panic_at_unimplemented_subpattern_type() {
2030 check_diagnostics(
2031 r#"
2032struct S { a: char}
2033fn main(v: S) {
2034 match v { S{ a } => {} }
2035 match v { S{ a: _x } => {} }
2036 match v { S{ a: 'a' } => {} }
2037 //^^^^^^^^^^^ Internal: match check bailed out
2038 match v { S{..} => {} }
2039 match v { _ => {} }
2040 match v { }
2041 //^ Missing match arm
2042}
2043"#,
2044 );
2045 }
2046
2047 #[test]
2048 fn binding() {
2049 check_diagnostics(
2050 r#"
2051fn main() {
2052 match true {
2053 _x @ true => {}
2054 false => {}
2055 }
2056 match true { _x @ true => {} }
2057 //^^^^ Missing match arm
2058}
2059"#,
2060 );
2061 }
2062
2063 #[test]
2064 fn binding_ref_has_correct_type() {
2065 // Asserts `PatKind::Binding(ref _x): bool`, not &bool.
2066 // If that's not true match checking will panic with "incompatible constructors"
2067 // FIXME: make facilities to test this directly like `tests::check_infer(..)`
2068 check_diagnostics(
2069 r#"
2070enum Foo { A }
2071fn main() {
2072 // FIXME: this should not bail out but current behavior is such as the old algorithm.
2073 // ExprValidator::validate_match(..) checks types of top level patterns incorrecly.
2074 match Foo::A {
2075 ref _x => {}
2076 // ^^^^^^ Internal: match check bailed out
2077 Foo::A => {}
2078 }
2079 match (true,) {
2080 (ref _x,) => {}
2081 (true,) => {}
2082 }
2083}
2084"#,
2085 );
2086 }
2087
2088 #[test]
2089 fn enum_non_exhaustive() {
2090 check_diagnostics(
2091 r#"
2092//- /lib.rs crate:lib
2093#[non_exhaustive]
2094pub enum E { A, B }
2095fn _local() {
2096 match E::A { _ => {} }
2097 match E::A {
2098 E::A => {}
2099 E::B => {}
2100 }
2101 match E::A {
2102 E::A | E::B => {}
2103 }
2104}
2105
2106//- /main.rs crate:main deps:lib
2107use lib::E;
2108fn main() {
2109 match E::A { _ => {} }
2110 match E::A {
2111 //^^^^ Missing match arm
2112 E::A => {}
2113 E::B => {}
2114 }
2115 match E::A {
2116 //^^^^ Missing match arm
2117 E::A | E::B => {}
2118 }
2119}
2120"#,
2121 );
2122 }
2123
2124 #[test]
2125 fn match_guard() {
2126 check_diagnostics(
2127 r#"
2128fn main() {
2129 match true {
2130 true if false => {}
2131 true => {}
2132 false => {}
2133 }
2134 match true {
2135 //^^^^ Missing match arm
2136 true if false => {}
2137 false => {}
2138 }
2139}
2140"#,
2141 );
2142 }
2143
2144 #[test]
2145 fn pattern_type_is_of_substitution() {
2146 check_diagnostics(
2147 r#"
2148struct Foo<T>(T);
2149struct Bar;
2150fn main() {
2151 match Foo(Bar) {
2152 _ | Foo(Bar) => {}
2153 }
2154}
2155"#,
2156 );
2157 }
2158
2159 #[test]
2160 fn record_struct_no_such_field() {
2161 check_diagnostics(
2162 r#"
2163struct Foo { }
2164fn main(f: Foo) {
2165 match f { Foo { bar } => () }
2166 // ^^^^^^^^^^^ Internal: match check bailed out
2167}
2168"#,
2169 );
2170 }
2171
2172 #[test]
2173 fn match_ergonomics_issue_9095() {
2174 check_diagnostics(
2175 r#"
2176enum Foo<T> { A(T) }
2177fn main() {
2178 match &Foo::A(true) {
2179 _ => {}
2180 Foo::A(_) => {}
2181 }
2182}
2183"#,
2184 );
2185 }
2186
2187 mod false_negatives {
2188 //! The implementation of match checking here is a work in progress. As we roll this out, we
2189 //! prefer false negatives to false positives (ideally there would be no false positives). This
2190 //! test module should document known false negatives. Eventually we will have a complete
2191 //! implementation of match checking and this module will be empty.
2192 //!
2193 //! The reasons for documenting known false negatives:
2194 //!
2195 //! 1. It acts as a backlog of work that can be done to improve the behavior of the system.
2196 //! 2. It ensures the code doesn't panic when handling these cases.
2197 use super::*;
2198
2199 #[test]
2200 fn integers() {
2201 // We don't currently check integer exhaustiveness.
2202 check_diagnostics(
2203 r#"
2204fn main() {
2205 match 5 {
2206 10 => (),
2207 // ^^ Internal: match check bailed out
2208 11..20 => (),
2209 }
2210}
2211"#,
2212 );
2213 }
2214
2215 #[test]
2216 fn reference_patterns_at_top_level() {
2217 check_diagnostics(
2218 r#"
2219fn main() {
2220 match &false {
2221 &true => {}
2222 // ^^^^^ Internal: match check bailed out
2223 }
2224}
2225 "#,
2226 );
2227 }
2228
2229 #[test]
2230 fn reference_patterns_in_fields() {
2231 check_diagnostics(
2232 r#"
2233fn main() {
2234 match (&false,) {
2235 (true,) => {}
2236 // ^^^^^^^ Internal: match check bailed out
2237 }
2238 match (&false,) {
2239 (&true,) => {}
2240 // ^^^^^^^^ Internal: match check bailed out
2241 }
2242}
2243 "#,
2244 );
2245 }
2246 }
945} 2247}