diff options
125 files changed, 6348 insertions, 1996 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5848e61c7..d909bc3d5 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -2,14 +2,20 @@ | |||
2 | # It is not intended for manual editing. | 2 | # It is not intended for manual editing. |
3 | [[package]] | 3 | [[package]] |
4 | name = "addr2line" | 4 | name = "addr2line" |
5 | version = "0.12.1" | 5 | version = "0.12.2" |
6 | source = "registry+https://github.com/rust-lang/crates.io-index" | 6 | source = "registry+https://github.com/rust-lang/crates.io-index" |
7 | checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" | 7 | checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c" |
8 | dependencies = [ | 8 | dependencies = [ |
9 | "gimli", | 9 | "gimli", |
10 | ] | 10 | ] |
11 | 11 | ||
12 | [[package]] | 12 | [[package]] |
13 | name = "adler32" | ||
14 | version = "1.1.0" | ||
15 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
16 | checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" | ||
17 | |||
18 | [[package]] | ||
13 | name = "aho-corasick" | 19 | name = "aho-corasick" |
14 | version = "0.7.10" | 20 | version = "0.7.10" |
15 | source = "registry+https://github.com/rust-lang/crates.io-index" | 21 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -55,22 +61,23 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" | |||
55 | 61 | ||
56 | [[package]] | 62 | [[package]] |
57 | name = "backtrace" | 63 | name = "backtrace" |
58 | version = "0.3.48" | 64 | version = "0.3.49" |
59 | source = "registry+https://github.com/rust-lang/crates.io-index" | 65 | source = "registry+https://github.com/rust-lang/crates.io-index" |
60 | checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" | 66 | checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c" |
61 | dependencies = [ | 67 | dependencies = [ |
62 | "addr2line", | 68 | "addr2line", |
63 | "cfg-if", | 69 | "cfg-if", |
64 | "libc", | 70 | "libc", |
71 | "miniz_oxide", | ||
65 | "object", | 72 | "object", |
66 | "rustc-demangle", | 73 | "rustc-demangle", |
67 | ] | 74 | ] |
68 | 75 | ||
69 | [[package]] | 76 | [[package]] |
70 | name = "base64" | 77 | name = "base64" |
71 | version = "0.12.1" | 78 | version = "0.12.2" |
72 | source = "registry+https://github.com/rust-lang/crates.io-index" | 79 | source = "registry+https://github.com/rust-lang/crates.io-index" |
73 | checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" | 80 | checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67" |
74 | 81 | ||
75 | [[package]] | 82 | [[package]] |
76 | name = "bitflags" | 83 | name = "bitflags" |
@@ -281,9 +288,9 @@ checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | |||
281 | 288 | ||
282 | [[package]] | 289 | [[package]] |
283 | name = "dtoa" | 290 | name = "dtoa" |
284 | version = "0.4.5" | 291 | version = "0.4.6" |
285 | source = "registry+https://github.com/rust-lang/crates.io-index" | 292 | source = "registry+https://github.com/rust-lang/crates.io-index" |
286 | checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" | 293 | checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" |
287 | 294 | ||
288 | [[package]] | 295 | [[package]] |
289 | name = "either" | 296 | name = "either" |
@@ -438,9 +445,9 @@ dependencies = [ | |||
438 | 445 | ||
439 | [[package]] | 446 | [[package]] |
440 | name = "hermit-abi" | 447 | name = "hermit-abi" |
441 | version = "0.1.13" | 448 | version = "0.1.14" |
442 | source = "registry+https://github.com/rust-lang/crates.io-index" | 449 | source = "registry+https://github.com/rust-lang/crates.io-index" |
443 | checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" | 450 | checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" |
444 | dependencies = [ | 451 | dependencies = [ |
445 | "libc", | 452 | "libc", |
446 | ] | 453 | ] |
@@ -528,9 +535,9 @@ dependencies = [ | |||
528 | 535 | ||
529 | [[package]] | 536 | [[package]] |
530 | name = "itoa" | 537 | name = "itoa" |
531 | version = "0.4.5" | 538 | version = "0.4.6" |
532 | source = "registry+https://github.com/rust-lang/crates.io-index" | 539 | source = "registry+https://github.com/rust-lang/crates.io-index" |
533 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" | 540 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" |
534 | 541 | ||
535 | [[package]] | 542 | [[package]] |
536 | name = "jemalloc-ctl" | 543 | name = "jemalloc-ctl" |
@@ -633,9 +640,9 @@ dependencies = [ | |||
633 | 640 | ||
634 | [[package]] | 641 | [[package]] |
635 | name = "lsp-server" | 642 | name = "lsp-server" |
636 | version = "0.3.2" | 643 | version = "0.3.3" |
637 | source = "registry+https://github.com/rust-lang/crates.io-index" | 644 | source = "registry+https://github.com/rust-lang/crates.io-index" |
638 | checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072" | 645 | checksum = "53b4ace8ebe5d2aff3687ce0ed507f6020d6a47a7de2b0d3d664ea237ffb0c62" |
639 | dependencies = [ | 646 | dependencies = [ |
640 | "crossbeam-channel", | 647 | "crossbeam-channel", |
641 | "log", | 648 | "log", |
@@ -695,6 +702,15 @@ dependencies = [ | |||
695 | ] | 702 | ] |
696 | 703 | ||
697 | [[package]] | 704 | [[package]] |
705 | name = "miniz_oxide" | ||
706 | version = "0.3.7" | ||
707 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
708 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" | ||
709 | dependencies = [ | ||
710 | "adler32", | ||
711 | ] | ||
712 | |||
713 | [[package]] | ||
698 | name = "mio" | 714 | name = "mio" |
699 | version = "0.6.22" | 715 | version = "0.6.22" |
700 | source = "registry+https://github.com/rust-lang/crates.io-index" | 716 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -778,9 +794,9 @@ dependencies = [ | |||
778 | 794 | ||
779 | [[package]] | 795 | [[package]] |
780 | name = "object" | 796 | name = "object" |
781 | version = "0.19.0" | 797 | version = "0.20.0" |
782 | source = "registry+https://github.com/rust-lang/crates.io-index" | 798 | source = "registry+https://github.com/rust-lang/crates.io-index" |
783 | checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" | 799 | checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" |
784 | 800 | ||
785 | [[package]] | 801 | [[package]] |
786 | name = "once_cell" | 802 | name = "once_cell" |
@@ -814,9 +830,9 @@ dependencies = [ | |||
814 | 830 | ||
815 | [[package]] | 831 | [[package]] |
816 | name = "paste" | 832 | name = "paste" |
817 | version = "0.1.16" | 833 | version = "0.1.18" |
818 | source = "registry+https://github.com/rust-lang/crates.io-index" | 834 | source = "registry+https://github.com/rust-lang/crates.io-index" |
819 | checksum = "d508492eeb1e5c38ee696371bf7b9fc33c83d46a7d451606b96458fbbbdc2dec" | 835 | checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" |
820 | dependencies = [ | 836 | dependencies = [ |
821 | "paste-impl", | 837 | "paste-impl", |
822 | "proc-macro-hack", | 838 | "proc-macro-hack", |
@@ -824,14 +840,11 @@ dependencies = [ | |||
824 | 840 | ||
825 | [[package]] | 841 | [[package]] |
826 | name = "paste-impl" | 842 | name = "paste-impl" |
827 | version = "0.1.16" | 843 | version = "0.1.18" |
828 | source = "registry+https://github.com/rust-lang/crates.io-index" | 844 | source = "registry+https://github.com/rust-lang/crates.io-index" |
829 | checksum = "84f328a6a63192b333fce5fbb4be79db6758a4d518dfac6d54412f1492f72d32" | 845 | checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" |
830 | dependencies = [ | 846 | dependencies = [ |
831 | "proc-macro-hack", | 847 | "proc-macro-hack", |
832 | "proc-macro2", | ||
833 | "quote", | ||
834 | "syn", | ||
835 | ] | 848 | ] |
836 | 849 | ||
837 | [[package]] | 850 | [[package]] |
@@ -856,9 +869,9 @@ dependencies = [ | |||
856 | 869 | ||
857 | [[package]] | 870 | [[package]] |
858 | name = "pico-args" | 871 | name = "pico-args" |
859 | version = "0.3.1" | 872 | version = "0.3.2" |
860 | source = "registry+https://github.com/rust-lang/crates.io-index" | 873 | source = "registry+https://github.com/rust-lang/crates.io-index" |
861 | checksum = "3ad1f1b834a05d42dae330066e9699a173b28185b3bdc3dbf14ca239585de8cc" | 874 | checksum = "6a71836ceac43f0349e3bd964f5bb902f7b003916f32a4ad00354dafc447fa8f" |
862 | 875 | ||
863 | [[package]] | 876 | [[package]] |
864 | name = "plain" | 877 | name = "plain" |
@@ -1062,6 +1075,7 @@ dependencies = [ | |||
1062 | "ra_hir", | 1075 | "ra_hir", |
1063 | "ra_ide_db", | 1076 | "ra_ide_db", |
1064 | "ra_prof", | 1077 | "ra_prof", |
1078 | "ra_ssr", | ||
1065 | "ra_syntax", | 1079 | "ra_syntax", |
1066 | "ra_text_edit", | 1080 | "ra_text_edit", |
1067 | "rand", | 1081 | "rand", |
@@ -1167,6 +1181,18 @@ dependencies = [ | |||
1167 | ] | 1181 | ] |
1168 | 1182 | ||
1169 | [[package]] | 1183 | [[package]] |
1184 | name = "ra_ssr" | ||
1185 | version = "0.1.0" | ||
1186 | dependencies = [ | ||
1187 | "ra_db", | ||
1188 | "ra_hir", | ||
1189 | "ra_ide_db", | ||
1190 | "ra_syntax", | ||
1191 | "ra_text_edit", | ||
1192 | "rustc-hash", | ||
1193 | ] | ||
1194 | |||
1195 | [[package]] | ||
1170 | name = "ra_syntax" | 1196 | name = "ra_syntax" |
1171 | version = "0.1.0" | 1197 | version = "0.1.0" |
1172 | dependencies = [ | 1198 | dependencies = [ |
@@ -1275,10 +1301,11 @@ dependencies = [ | |||
1275 | 1301 | ||
1276 | [[package]] | 1302 | [[package]] |
1277 | name = "rayon" | 1303 | name = "rayon" |
1278 | version = "1.3.0" | 1304 | version = "1.3.1" |
1279 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1280 | checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" | 1306 | checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080" |
1281 | dependencies = [ | 1307 | dependencies = [ |
1308 | "autocfg", | ||
1282 | "crossbeam-deque", | 1309 | "crossbeam-deque", |
1283 | "either", | 1310 | "either", |
1284 | "rayon-core", | 1311 | "rayon-core", |
@@ -1286,9 +1313,9 @@ dependencies = [ | |||
1286 | 1313 | ||
1287 | [[package]] | 1314 | [[package]] |
1288 | name = "rayon-core" | 1315 | name = "rayon-core" |
1289 | version = "1.7.0" | 1316 | version = "1.7.1" |
1290 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1291 | checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" | 1318 | checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280" |
1292 | dependencies = [ | 1319 | dependencies = [ |
1293 | "crossbeam-deque", | 1320 | "crossbeam-deque", |
1294 | "crossbeam-queue", | 1321 | "crossbeam-queue", |
@@ -1323,15 +1350,15 @@ checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" | |||
1323 | 1350 | ||
1324 | [[package]] | 1351 | [[package]] |
1325 | name = "relative-path" | 1352 | name = "relative-path" |
1326 | version = "1.0.0" | 1353 | version = "1.2.1" |
1327 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1328 | checksum = "bedde000f40f2921ce439ea165c9c53fd629bfa115140c72e22aceacb4a21954" | 1355 | checksum = "c602122c47b382cd045b10866a084b184035d45d8c2609cdd3762852ddfae2a1" |
1329 | 1356 | ||
1330 | [[package]] | 1357 | [[package]] |
1331 | name = "remove_dir_all" | 1358 | name = "remove_dir_all" |
1332 | version = "0.5.2" | 1359 | version = "0.5.3" |
1333 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1360 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1334 | checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" | 1361 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" |
1335 | dependencies = [ | 1362 | dependencies = [ |
1336 | "winapi 0.3.8", | 1363 | "winapi 0.3.8", |
1337 | ] | 1364 | ] |
@@ -1505,18 +1532,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | |||
1505 | 1532 | ||
1506 | [[package]] | 1533 | [[package]] |
1507 | name = "serde" | 1534 | name = "serde" |
1508 | version = "1.0.111" | 1535 | version = "1.0.113" |
1509 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1510 | checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" | 1537 | checksum = "6135c78461981c79497158ef777264c51d9d0f4f3fc3a4d22b915900e42dac6a" |
1511 | dependencies = [ | 1538 | dependencies = [ |
1512 | "serde_derive", | 1539 | "serde_derive", |
1513 | ] | 1540 | ] |
1514 | 1541 | ||
1515 | [[package]] | 1542 | [[package]] |
1516 | name = "serde_derive" | 1543 | name = "serde_derive" |
1517 | version = "1.0.111" | 1544 | version = "1.0.113" |
1518 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1545 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1519 | checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" | 1546 | checksum = "93c5eaa17d0954cb481cdcfffe9d84fcfa7a1a9f2349271e678677be4c26ae31" |
1520 | dependencies = [ | 1547 | dependencies = [ |
1521 | "proc-macro2", | 1548 | "proc-macro2", |
1522 | "quote", | 1549 | "quote", |
@@ -1536,9 +1563,9 @@ dependencies = [ | |||
1536 | 1563 | ||
1537 | [[package]] | 1564 | [[package]] |
1538 | name = "serde_repr" | 1565 | name = "serde_repr" |
1539 | version = "0.1.5" | 1566 | version = "0.1.6" |
1540 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1541 | checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" | 1568 | checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" |
1542 | dependencies = [ | 1569 | dependencies = [ |
1543 | "proc-macro2", | 1570 | "proc-macro2", |
1544 | "quote", | 1571 | "quote", |
@@ -1590,9 +1617,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | |||
1590 | 1617 | ||
1591 | [[package]] | 1618 | [[package]] |
1592 | name = "syn" | 1619 | name = "syn" |
1593 | version = "1.0.31" | 1620 | version = "1.0.32" |
1594 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1621 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1595 | checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" | 1622 | checksum = "a994520748611c17d163e81b6c4a4b13d11b7f63884362ab2efac3aa9cf16d00" |
1596 | dependencies = [ | 1623 | dependencies = [ |
1597 | "proc-macro2", | 1624 | "proc-macro2", |
1598 | "quote", | 1625 | "quote", |
@@ -1688,6 +1715,12 @@ dependencies = [ | |||
1688 | ] | 1715 | ] |
1689 | 1716 | ||
1690 | [[package]] | 1717 | [[package]] |
1718 | name = "tinyvec" | ||
1719 | version = "0.3.3" | ||
1720 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1721 | checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" | ||
1722 | |||
1723 | [[package]] | ||
1691 | name = "unicode-bidi" | 1724 | name = "unicode-bidi" |
1692 | version = "0.3.4" | 1725 | version = "0.3.4" |
1693 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1698,11 +1731,11 @@ dependencies = [ | |||
1698 | 1731 | ||
1699 | [[package]] | 1732 | [[package]] |
1700 | name = "unicode-normalization" | 1733 | name = "unicode-normalization" |
1701 | version = "0.1.12" | 1734 | version = "0.1.13" |
1702 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1703 | checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" | 1736 | checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" |
1704 | dependencies = [ | 1737 | dependencies = [ |
1705 | "smallvec", | 1738 | "tinyvec", |
1706 | ] | 1739 | ] |
1707 | 1740 | ||
1708 | [[package]] | 1741 | [[package]] |
@@ -1730,6 +1763,18 @@ dependencies = [ | |||
1730 | ] | 1763 | ] |
1731 | 1764 | ||
1732 | [[package]] | 1765 | [[package]] |
1766 | name = "vfs" | ||
1767 | version = "0.1.0" | ||
1768 | dependencies = [ | ||
1769 | "crossbeam-channel", | ||
1770 | "globset", | ||
1771 | "jod-thread", | ||
1772 | "paths", | ||
1773 | "rustc-hash", | ||
1774 | "walkdir", | ||
1775 | ] | ||
1776 | |||
1777 | [[package]] | ||
1733 | name = "walkdir" | 1778 | name = "walkdir" |
1734 | version = "2.3.1" | 1779 | version = "2.3.1" |
1735 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" |
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index c7ce0c42f..190c50913 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | //! relative paths. | 2 | //! relative paths. |
3 | use std::{ | 3 | use std::{ |
4 | convert::{TryFrom, TryInto}, | 4 | convert::{TryFrom, TryInto}, |
5 | ops, | 5 | io, ops, |
6 | path::{Component, Path, PathBuf}, | 6 | path::{Component, Path, PathBuf}, |
7 | }; | 7 | }; |
8 | 8 | ||
@@ -46,6 +46,9 @@ impl TryFrom<&str> for AbsPathBuf { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | impl AbsPathBuf { | 48 | impl AbsPathBuf { |
49 | pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> { | ||
50 | path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap()) | ||
51 | } | ||
49 | pub fn as_path(&self) -> &AbsPath { | 52 | pub fn as_path(&self) -> &AbsPath { |
50 | AbsPath::new_unchecked(self.0.as_path()) | 53 | AbsPath::new_unchecked(self.0.as_path()) |
51 | } | 54 | } |
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs index edd8255f4..ee614de72 100644 --- a/crates/ra_assists/src/assist_context.rs +++ b/crates/ra_assists/src/assist_context.rs | |||
@@ -252,7 +252,7 @@ impl AssistBuilder { | |||
252 | pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { | 252 | pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { |
253 | let node = rewriter.rewrite_root().unwrap(); | 253 | let node = rewriter.rewrite_root().unwrap(); |
254 | let new = rewriter.rewrite(&node); | 254 | let new = rewriter.rewrite(&node); |
255 | algo::diff(&node, &new).into_text_edit(&mut self.edit) | 255 | algo::diff(&node, &new).into_text_edit(&mut self.edit); |
256 | } | 256 | } |
257 | 257 | ||
258 | // FIXME: kill this API | 258 | // FIXME: kill this API |
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index 0197a8cf0..b4784c333 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -1,7 +1,10 @@ | |||
1 | use hir; | 1 | use hir; |
2 | use ra_syntax::{ast, AstNode, SmolStr, TextRange}; | 2 | use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode}; |
3 | 3 | ||
4 | use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists}; | 4 | use crate::{ |
5 | utils::{find_insert_use_container, insert_use_statement}, | ||
6 | AssistContext, AssistId, Assists, | ||
7 | }; | ||
5 | 8 | ||
6 | // Assist: replace_qualified_name_with_use | 9 | // Assist: replace_qualified_name_with_use |
7 | // | 10 | // |
@@ -39,16 +42,18 @@ pub(crate) fn replace_qualified_name_with_use( | |||
39 | target, | 42 | target, |
40 | |builder| { | 43 | |builder| { |
41 | let path_to_import = hir_path.mod_path().clone(); | 44 | let path_to_import = hir_path.mod_path().clone(); |
45 | let container = match find_insert_use_container(path.syntax(), ctx) { | ||
46 | Some(c) => c, | ||
47 | None => return, | ||
48 | }; | ||
42 | insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); | 49 | insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); |
43 | 50 | ||
44 | if let Some(last) = path.segment() { | 51 | // Now that we've brought the name into scope, re-qualify all paths that could be |
45 | // Here we are assuming the assist will provide a correct use statement | 52 | // affected (that is, all paths inside the node we added the `use` to). |
46 | // so we can delete the path qualifier | 53 | let mut rewriter = SyntaxRewriter::default(); |
47 | builder.delete(TextRange::new( | 54 | let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone()); |
48 | path.syntax().text_range().start(), | 55 | shorten_paths(&mut rewriter, syntax, path); |
49 | last.syntax().text_range().start(), | 56 | builder.rewrite(rewriter); |
50 | )); | ||
51 | } | ||
52 | }, | 57 | }, |
53 | ) | 58 | ) |
54 | } | 59 | } |
@@ -73,6 +78,69 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { | |||
73 | Some(ps) | 78 | Some(ps) |
74 | } | 79 | } |
75 | 80 | ||
81 | /// Adds replacements to `re` that shorten `path` in all descendants of `node`. | ||
82 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) { | ||
83 | for child in node.children() { | ||
84 | match_ast! { | ||
85 | match child { | ||
86 | // Don't modify `use` items, as this can break the `use` item when injecting a new | ||
87 | // import into the use tree. | ||
88 | ast::UseItem(_it) => continue, | ||
89 | // Don't descend into submodules, they don't have the same `use` items in scope. | ||
90 | ast::Module(_it) => continue, | ||
91 | |||
92 | ast::Path(p) => { | ||
93 | match maybe_replace_path(rewriter, p.clone(), path.clone()) { | ||
94 | Some(()) => {}, | ||
95 | None => shorten_paths(rewriter, p.syntax().clone(), path.clone()), | ||
96 | } | ||
97 | }, | ||
98 | _ => shorten_paths(rewriter, child, path.clone()), | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | fn maybe_replace_path( | ||
105 | rewriter: &mut SyntaxRewriter<'static>, | ||
106 | path: ast::Path, | ||
107 | target: ast::Path, | ||
108 | ) -> Option<()> { | ||
109 | if !path_eq(path.clone(), target.clone()) { | ||
110 | return None; | ||
111 | } | ||
112 | |||
113 | // Shorten `path`, leaving only its last segment. | ||
114 | if let Some(parent) = path.qualifier() { | ||
115 | rewriter.delete(parent.syntax()); | ||
116 | } | ||
117 | if let Some(double_colon) = path.coloncolon_token() { | ||
118 | rewriter.delete(&double_colon); | ||
119 | } | ||
120 | |||
121 | Some(()) | ||
122 | } | ||
123 | |||
124 | fn path_eq(lhs: ast::Path, rhs: ast::Path) -> bool { | ||
125 | let mut lhs_curr = lhs; | ||
126 | let mut rhs_curr = rhs; | ||
127 | loop { | ||
128 | match (lhs_curr.segment(), rhs_curr.segment()) { | ||
129 | (Some(lhs), Some(rhs)) if lhs.syntax().text() == rhs.syntax().text() => (), | ||
130 | _ => return false, | ||
131 | } | ||
132 | |||
133 | match (lhs_curr.qualifier(), rhs_curr.qualifier()) { | ||
134 | (Some(lhs), Some(rhs)) => { | ||
135 | lhs_curr = lhs; | ||
136 | rhs_curr = rhs; | ||
137 | } | ||
138 | (None, None) => return true, | ||
139 | _ => return false, | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
76 | #[cfg(test)] | 144 | #[cfg(test)] |
77 | mod tests { | 145 | mod tests { |
78 | use crate::tests::{check_assist, check_assist_not_applicable}; | 146 | use crate::tests::{check_assist, check_assist_not_applicable}; |
@@ -83,10 +151,10 @@ mod tests { | |||
83 | fn test_replace_add_use_no_anchor() { | 151 | fn test_replace_add_use_no_anchor() { |
84 | check_assist( | 152 | check_assist( |
85 | replace_qualified_name_with_use, | 153 | replace_qualified_name_with_use, |
86 | " | 154 | r" |
87 | std::fmt::Debug<|> | 155 | std::fmt::Debug<|> |
88 | ", | 156 | ", |
89 | " | 157 | r" |
90 | use std::fmt::Debug; | 158 | use std::fmt::Debug; |
91 | 159 | ||
92 | Debug | 160 | Debug |
@@ -97,13 +165,13 @@ Debug | |||
97 | fn test_replace_add_use_no_anchor_with_item_below() { | 165 | fn test_replace_add_use_no_anchor_with_item_below() { |
98 | check_assist( | 166 | check_assist( |
99 | replace_qualified_name_with_use, | 167 | replace_qualified_name_with_use, |
100 | " | 168 | r" |
101 | std::fmt::Debug<|> | 169 | std::fmt::Debug<|> |
102 | 170 | ||
103 | fn main() { | 171 | fn main() { |
104 | } | 172 | } |
105 | ", | 173 | ", |
106 | " | 174 | r" |
107 | use std::fmt::Debug; | 175 | use std::fmt::Debug; |
108 | 176 | ||
109 | Debug | 177 | Debug |
@@ -118,13 +186,13 @@ fn main() { | |||
118 | fn test_replace_add_use_no_anchor_with_item_above() { | 186 | fn test_replace_add_use_no_anchor_with_item_above() { |
119 | check_assist( | 187 | check_assist( |
120 | replace_qualified_name_with_use, | 188 | replace_qualified_name_with_use, |
121 | " | 189 | r" |
122 | fn main() { | 190 | fn main() { |
123 | } | 191 | } |
124 | 192 | ||
125 | std::fmt::Debug<|> | 193 | std::fmt::Debug<|> |
126 | ", | 194 | ", |
127 | " | 195 | r" |
128 | use std::fmt::Debug; | 196 | use std::fmt::Debug; |
129 | 197 | ||
130 | fn main() { | 198 | fn main() { |
@@ -139,10 +207,10 @@ Debug | |||
139 | fn test_replace_add_use_no_anchor_2seg() { | 207 | fn test_replace_add_use_no_anchor_2seg() { |
140 | check_assist( | 208 | check_assist( |
141 | replace_qualified_name_with_use, | 209 | replace_qualified_name_with_use, |
142 | " | 210 | r" |
143 | std::fmt<|>::Debug | 211 | std::fmt<|>::Debug |
144 | ", | 212 | ", |
145 | " | 213 | r" |
146 | use std::fmt; | 214 | use std::fmt; |
147 | 215 | ||
148 | fmt::Debug | 216 | fmt::Debug |
@@ -154,13 +222,13 @@ fmt::Debug | |||
154 | fn test_replace_add_use() { | 222 | fn test_replace_add_use() { |
155 | check_assist( | 223 | check_assist( |
156 | replace_qualified_name_with_use, | 224 | replace_qualified_name_with_use, |
157 | " | 225 | r" |
158 | use stdx; | 226 | use stdx; |
159 | 227 | ||
160 | impl std::fmt::Debug<|> for Foo { | 228 | impl std::fmt::Debug<|> for Foo { |
161 | } | 229 | } |
162 | ", | 230 | ", |
163 | " | 231 | r" |
164 | use stdx; | 232 | use stdx; |
165 | use std::fmt::Debug; | 233 | use std::fmt::Debug; |
166 | 234 | ||
@@ -174,11 +242,11 @@ impl Debug for Foo { | |||
174 | fn test_replace_file_use_other_anchor() { | 242 | fn test_replace_file_use_other_anchor() { |
175 | check_assist( | 243 | check_assist( |
176 | replace_qualified_name_with_use, | 244 | replace_qualified_name_with_use, |
177 | " | 245 | r" |
178 | impl std::fmt::Debug<|> for Foo { | 246 | impl std::fmt::Debug<|> for Foo { |
179 | } | 247 | } |
180 | ", | 248 | ", |
181 | " | 249 | r" |
182 | use std::fmt::Debug; | 250 | use std::fmt::Debug; |
183 | 251 | ||
184 | impl Debug for Foo { | 252 | impl Debug for Foo { |
@@ -191,11 +259,11 @@ impl Debug for Foo { | |||
191 | fn test_replace_add_use_other_anchor_indent() { | 259 | fn test_replace_add_use_other_anchor_indent() { |
192 | check_assist( | 260 | check_assist( |
193 | replace_qualified_name_with_use, | 261 | replace_qualified_name_with_use, |
194 | " | 262 | r" |
195 | impl std::fmt::Debug<|> for Foo { | 263 | impl std::fmt::Debug<|> for Foo { |
196 | } | 264 | } |
197 | ", | 265 | ", |
198 | " | 266 | r" |
199 | use std::fmt::Debug; | 267 | use std::fmt::Debug; |
200 | 268 | ||
201 | impl Debug for Foo { | 269 | impl Debug for Foo { |
@@ -208,13 +276,13 @@ impl Debug for Foo { | |||
208 | fn test_replace_split_different() { | 276 | fn test_replace_split_different() { |
209 | check_assist( | 277 | check_assist( |
210 | replace_qualified_name_with_use, | 278 | replace_qualified_name_with_use, |
211 | " | 279 | r" |
212 | use std::fmt; | 280 | use std::fmt; |
213 | 281 | ||
214 | impl std::io<|> for Foo { | 282 | impl std::io<|> for Foo { |
215 | } | 283 | } |
216 | ", | 284 | ", |
217 | " | 285 | r" |
218 | use std::{io, fmt}; | 286 | use std::{io, fmt}; |
219 | 287 | ||
220 | impl io for Foo { | 288 | impl io for Foo { |
@@ -227,13 +295,13 @@ impl io for Foo { | |||
227 | fn test_replace_split_self_for_use() { | 295 | fn test_replace_split_self_for_use() { |
228 | check_assist( | 296 | check_assist( |
229 | replace_qualified_name_with_use, | 297 | replace_qualified_name_with_use, |
230 | " | 298 | r" |
231 | use std::fmt; | 299 | use std::fmt; |
232 | 300 | ||
233 | impl std::fmt::Debug<|> for Foo { | 301 | impl std::fmt::Debug<|> for Foo { |
234 | } | 302 | } |
235 | ", | 303 | ", |
236 | " | 304 | r" |
237 | use std::fmt::{self, Debug, }; | 305 | use std::fmt::{self, Debug, }; |
238 | 306 | ||
239 | impl Debug for Foo { | 307 | impl Debug for Foo { |
@@ -246,13 +314,13 @@ impl Debug for Foo { | |||
246 | fn test_replace_split_self_for_target() { | 314 | fn test_replace_split_self_for_target() { |
247 | check_assist( | 315 | check_assist( |
248 | replace_qualified_name_with_use, | 316 | replace_qualified_name_with_use, |
249 | " | 317 | r" |
250 | use std::fmt::Debug; | 318 | use std::fmt::Debug; |
251 | 319 | ||
252 | impl std::fmt<|> for Foo { | 320 | impl std::fmt<|> for Foo { |
253 | } | 321 | } |
254 | ", | 322 | ", |
255 | " | 323 | r" |
256 | use std::fmt::{self, Debug}; | 324 | use std::fmt::{self, Debug}; |
257 | 325 | ||
258 | impl fmt for Foo { | 326 | impl fmt for Foo { |
@@ -265,13 +333,13 @@ impl fmt for Foo { | |||
265 | fn test_replace_add_to_nested_self_nested() { | 333 | fn test_replace_add_to_nested_self_nested() { |
266 | check_assist( | 334 | check_assist( |
267 | replace_qualified_name_with_use, | 335 | replace_qualified_name_with_use, |
268 | " | 336 | r" |
269 | use std::fmt::{Debug, nested::{Display}}; | 337 | use std::fmt::{Debug, nested::{Display}}; |
270 | 338 | ||
271 | impl std::fmt::nested<|> for Foo { | 339 | impl std::fmt::nested<|> for Foo { |
272 | } | 340 | } |
273 | ", | 341 | ", |
274 | " | 342 | r" |
275 | use std::fmt::{Debug, nested::{Display, self}}; | 343 | use std::fmt::{Debug, nested::{Display, self}}; |
276 | 344 | ||
277 | impl nested for Foo { | 345 | impl nested for Foo { |
@@ -284,13 +352,13 @@ impl nested for Foo { | |||
284 | fn test_replace_add_to_nested_self_already_included() { | 352 | fn test_replace_add_to_nested_self_already_included() { |
285 | check_assist( | 353 | check_assist( |
286 | replace_qualified_name_with_use, | 354 | replace_qualified_name_with_use, |
287 | " | 355 | r" |
288 | use std::fmt::{Debug, nested::{self, Display}}; | 356 | use std::fmt::{Debug, nested::{self, Display}}; |
289 | 357 | ||
290 | impl std::fmt::nested<|> for Foo { | 358 | impl std::fmt::nested<|> for Foo { |
291 | } | 359 | } |
292 | ", | 360 | ", |
293 | " | 361 | r" |
294 | use std::fmt::{Debug, nested::{self, Display}}; | 362 | use std::fmt::{Debug, nested::{self, Display}}; |
295 | 363 | ||
296 | impl nested for Foo { | 364 | impl nested for Foo { |
@@ -303,13 +371,13 @@ impl nested for Foo { | |||
303 | fn test_replace_add_to_nested_nested() { | 371 | fn test_replace_add_to_nested_nested() { |
304 | check_assist( | 372 | check_assist( |
305 | replace_qualified_name_with_use, | 373 | replace_qualified_name_with_use, |
306 | " | 374 | r" |
307 | use std::fmt::{Debug, nested::{Display}}; | 375 | use std::fmt::{Debug, nested::{Display}}; |
308 | 376 | ||
309 | impl std::fmt::nested::Debug<|> for Foo { | 377 | impl std::fmt::nested::Debug<|> for Foo { |
310 | } | 378 | } |
311 | ", | 379 | ", |
312 | " | 380 | r" |
313 | use std::fmt::{Debug, nested::{Display, Debug}}; | 381 | use std::fmt::{Debug, nested::{Display, Debug}}; |
314 | 382 | ||
315 | impl Debug for Foo { | 383 | impl Debug for Foo { |
@@ -322,13 +390,13 @@ impl Debug for Foo { | |||
322 | fn test_replace_split_common_target_longer() { | 390 | fn test_replace_split_common_target_longer() { |
323 | check_assist( | 391 | check_assist( |
324 | replace_qualified_name_with_use, | 392 | replace_qualified_name_with_use, |
325 | " | 393 | r" |
326 | use std::fmt::Debug; | 394 | use std::fmt::Debug; |
327 | 395 | ||
328 | impl std::fmt::nested::Display<|> for Foo { | 396 | impl std::fmt::nested::Display<|> for Foo { |
329 | } | 397 | } |
330 | ", | 398 | ", |
331 | " | 399 | r" |
332 | use std::fmt::{nested::Display, Debug}; | 400 | use std::fmt::{nested::Display, Debug}; |
333 | 401 | ||
334 | impl Display for Foo { | 402 | impl Display for Foo { |
@@ -341,13 +409,13 @@ impl Display for Foo { | |||
341 | fn test_replace_split_common_use_longer() { | 409 | fn test_replace_split_common_use_longer() { |
342 | check_assist( | 410 | check_assist( |
343 | replace_qualified_name_with_use, | 411 | replace_qualified_name_with_use, |
344 | " | 412 | r" |
345 | use std::fmt::nested::Debug; | 413 | use std::fmt::nested::Debug; |
346 | 414 | ||
347 | impl std::fmt::Display<|> for Foo { | 415 | impl std::fmt::Display<|> for Foo { |
348 | } | 416 | } |
349 | ", | 417 | ", |
350 | " | 418 | r" |
351 | use std::fmt::{Display, nested::Debug}; | 419 | use std::fmt::{Display, nested::Debug}; |
352 | 420 | ||
353 | impl Display for Foo { | 421 | impl Display for Foo { |
@@ -360,7 +428,7 @@ impl Display for Foo { | |||
360 | fn test_replace_use_nested_import() { | 428 | fn test_replace_use_nested_import() { |
361 | check_assist( | 429 | check_assist( |
362 | replace_qualified_name_with_use, | 430 | replace_qualified_name_with_use, |
363 | " | 431 | r" |
364 | use crate::{ | 432 | use crate::{ |
365 | ty::{Substs, Ty}, | 433 | ty::{Substs, Ty}, |
366 | AssocItem, | 434 | AssocItem, |
@@ -368,7 +436,7 @@ use crate::{ | |||
368 | 436 | ||
369 | fn foo() { crate::ty::lower<|>::trait_env() } | 437 | fn foo() { crate::ty::lower<|>::trait_env() } |
370 | ", | 438 | ", |
371 | " | 439 | r" |
372 | use crate::{ | 440 | use crate::{ |
373 | ty::{Substs, Ty, lower}, | 441 | ty::{Substs, Ty, lower}, |
374 | AssocItem, | 442 | AssocItem, |
@@ -383,13 +451,13 @@ fn foo() { lower::trait_env() } | |||
383 | fn test_replace_alias() { | 451 | fn test_replace_alias() { |
384 | check_assist( | 452 | check_assist( |
385 | replace_qualified_name_with_use, | 453 | replace_qualified_name_with_use, |
386 | " | 454 | r" |
387 | use std::fmt as foo; | 455 | use std::fmt as foo; |
388 | 456 | ||
389 | impl foo::Debug<|> for Foo { | 457 | impl foo::Debug<|> for Foo { |
390 | } | 458 | } |
391 | ", | 459 | ", |
392 | " | 460 | r" |
393 | use std::fmt as foo; | 461 | use std::fmt as foo; |
394 | 462 | ||
395 | impl Debug for Foo { | 463 | impl Debug for Foo { |
@@ -402,7 +470,7 @@ impl Debug for Foo { | |||
402 | fn test_replace_not_applicable_one_segment() { | 470 | fn test_replace_not_applicable_one_segment() { |
403 | check_assist_not_applicable( | 471 | check_assist_not_applicable( |
404 | replace_qualified_name_with_use, | 472 | replace_qualified_name_with_use, |
405 | " | 473 | r" |
406 | impl foo<|> for Foo { | 474 | impl foo<|> for Foo { |
407 | } | 475 | } |
408 | ", | 476 | ", |
@@ -413,7 +481,7 @@ impl foo<|> for Foo { | |||
413 | fn test_replace_not_applicable_in_use() { | 481 | fn test_replace_not_applicable_in_use() { |
414 | check_assist_not_applicable( | 482 | check_assist_not_applicable( |
415 | replace_qualified_name_with_use, | 483 | replace_qualified_name_with_use, |
416 | " | 484 | r" |
417 | use std::fmt<|>; | 485 | use std::fmt<|>; |
418 | ", | 486 | ", |
419 | ); | 487 | ); |
@@ -423,14 +491,14 @@ use std::fmt<|>; | |||
423 | fn test_replace_add_use_no_anchor_in_mod_mod() { | 491 | fn test_replace_add_use_no_anchor_in_mod_mod() { |
424 | check_assist( | 492 | check_assist( |
425 | replace_qualified_name_with_use, | 493 | replace_qualified_name_with_use, |
426 | " | 494 | r" |
427 | mod foo { | 495 | mod foo { |
428 | mod bar { | 496 | mod bar { |
429 | std::fmt::Debug<|> | 497 | std::fmt::Debug<|> |
430 | } | 498 | } |
431 | } | 499 | } |
432 | ", | 500 | ", |
433 | " | 501 | r" |
434 | mod foo { | 502 | mod foo { |
435 | mod bar { | 503 | mod bar { |
436 | use std::fmt::Debug; | 504 | use std::fmt::Debug; |
@@ -446,14 +514,14 @@ mod foo { | |||
446 | fn inserts_imports_after_inner_attributes() { | 514 | fn inserts_imports_after_inner_attributes() { |
447 | check_assist( | 515 | check_assist( |
448 | replace_qualified_name_with_use, | 516 | replace_qualified_name_with_use, |
449 | " | 517 | r" |
450 | #![allow(dead_code)] | 518 | #![allow(dead_code)] |
451 | 519 | ||
452 | fn main() { | 520 | fn main() { |
453 | std::fmt::Debug<|> | 521 | std::fmt::Debug<|> |
454 | } | 522 | } |
455 | ", | 523 | ", |
456 | " | 524 | r" |
457 | #![allow(dead_code)] | 525 | #![allow(dead_code)] |
458 | use std::fmt::Debug; | 526 | use std::fmt::Debug; |
459 | 527 | ||
@@ -463,4 +531,116 @@ fn main() { | |||
463 | ", | 531 | ", |
464 | ); | 532 | ); |
465 | } | 533 | } |
534 | |||
535 | #[test] | ||
536 | fn replaces_all_affected_paths() { | ||
537 | check_assist( | ||
538 | replace_qualified_name_with_use, | ||
539 | r" | ||
540 | fn main() { | ||
541 | std::fmt::Debug<|>; | ||
542 | let x: std::fmt::Debug = std::fmt::Debug; | ||
543 | } | ||
544 | ", | ||
545 | r" | ||
546 | use std::fmt::Debug; | ||
547 | |||
548 | fn main() { | ||
549 | Debug; | ||
550 | let x: Debug = Debug; | ||
551 | } | ||
552 | ", | ||
553 | ); | ||
554 | } | ||
555 | |||
556 | #[test] | ||
557 | fn replaces_all_affected_paths_mod() { | ||
558 | check_assist( | ||
559 | replace_qualified_name_with_use, | ||
560 | r" | ||
561 | mod m { | ||
562 | fn f() { | ||
563 | std::fmt::Debug<|>; | ||
564 | let x: std::fmt::Debug = std::fmt::Debug; | ||
565 | } | ||
566 | fn g() { | ||
567 | std::fmt::Debug; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | fn f() { | ||
572 | std::fmt::Debug; | ||
573 | } | ||
574 | ", | ||
575 | r" | ||
576 | mod m { | ||
577 | use std::fmt::Debug; | ||
578 | |||
579 | fn f() { | ||
580 | Debug; | ||
581 | let x: Debug = Debug; | ||
582 | } | ||
583 | fn g() { | ||
584 | Debug; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | fn f() { | ||
589 | std::fmt::Debug; | ||
590 | } | ||
591 | ", | ||
592 | ); | ||
593 | } | ||
594 | |||
595 | #[test] | ||
596 | fn does_not_replace_in_submodules() { | ||
597 | check_assist( | ||
598 | replace_qualified_name_with_use, | ||
599 | r" | ||
600 | fn main() { | ||
601 | std::fmt::Debug<|>; | ||
602 | } | ||
603 | |||
604 | mod sub { | ||
605 | fn f() { | ||
606 | std::fmt::Debug; | ||
607 | } | ||
608 | } | ||
609 | ", | ||
610 | r" | ||
611 | use std::fmt::Debug; | ||
612 | |||
613 | fn main() { | ||
614 | Debug; | ||
615 | } | ||
616 | |||
617 | mod sub { | ||
618 | fn f() { | ||
619 | std::fmt::Debug; | ||
620 | } | ||
621 | } | ||
622 | ", | ||
623 | ); | ||
624 | } | ||
625 | |||
626 | #[test] | ||
627 | fn does_not_replace_in_use() { | ||
628 | check_assist( | ||
629 | replace_qualified_name_with_use, | ||
630 | r" | ||
631 | use std::fmt::Display; | ||
632 | |||
633 | fn main() { | ||
634 | std::fmt<|>; | ||
635 | } | ||
636 | ", | ||
637 | r" | ||
638 | use std::fmt::{self, Display}; | ||
639 | |||
640 | fn main() { | ||
641 | fmt; | ||
642 | } | ||
643 | ", | ||
644 | ); | ||
645 | } | ||
466 | } | 646 | } |
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 0038a9764..c1ff0de7b 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -13,7 +13,7 @@ use rustc_hash::FxHashSet; | |||
13 | 13 | ||
14 | use crate::assist_config::SnippetCap; | 14 | use crate::assist_config::SnippetCap; |
15 | 15 | ||
16 | pub(crate) use insert_use::insert_use_statement; | 16 | pub(crate) use insert_use::{find_insert_use_container, insert_use_statement}; |
17 | 17 | ||
18 | #[derive(Clone, Copy, Debug)] | 18 | #[derive(Clone, Copy, Debug)] |
19 | pub(crate) enum Cursor<'a> { | 19 | pub(crate) enum Cursor<'a> { |
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs index 0ee43482f..8c4f33e59 100644 --- a/crates/ra_assists/src/utils/insert_use.rs +++ b/crates/ra_assists/src/utils/insert_use.rs | |||
@@ -12,6 +12,20 @@ use ra_syntax::{ | |||
12 | use ra_text_edit::TextEditBuilder; | 12 | use ra_text_edit::TextEditBuilder; |
13 | 13 | ||
14 | use crate::assist_context::AssistContext; | 14 | use crate::assist_context::AssistContext; |
15 | use either::Either; | ||
16 | |||
17 | /// Determines the containing syntax node in which to insert a `use` statement affecting `position`. | ||
18 | pub(crate) fn find_insert_use_container( | ||
19 | position: &SyntaxNode, | ||
20 | ctx: &AssistContext, | ||
21 | ) -> Option<Either<ast::ItemList, ast::SourceFile>> { | ||
22 | ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| { | ||
23 | if let Some(module) = ast::Module::cast(n.clone()) { | ||
24 | return module.item_list().map(|it| Either::Left(it)); | ||
25 | } | ||
26 | Some(Either::Right(ast::SourceFile::cast(n)?)) | ||
27 | }) | ||
28 | } | ||
15 | 29 | ||
16 | /// Creates and inserts a use statement for the given path to import. | 30 | /// Creates and inserts a use statement for the given path to import. |
17 | /// The use statement is inserted in the scope most appropriate to the | 31 | /// The use statement is inserted in the scope most appropriate to the |
@@ -24,15 +38,11 @@ pub(crate) fn insert_use_statement( | |||
24 | builder: &mut TextEditBuilder, | 38 | builder: &mut TextEditBuilder, |
25 | ) { | 39 | ) { |
26 | let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); | 40 | let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); |
27 | let container = ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| { | 41 | let container = find_insert_use_container(position, ctx); |
28 | if let Some(module) = ast::Module::cast(n.clone()) { | ||
29 | return module.item_list().map(|it| it.syntax().clone()); | ||
30 | } | ||
31 | ast::SourceFile::cast(n).map(|it| it.syntax().clone()) | ||
32 | }); | ||
33 | 42 | ||
34 | if let Some(container) = container { | 43 | if let Some(container) = container { |
35 | let action = best_action_for_target(container, position.clone(), &target); | 44 | let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone()); |
45 | let action = best_action_for_target(syntax, position.clone(), &target); | ||
36 | make_assist(&action, &target, builder); | 46 | make_assist(&action, &target, builder); |
37 | } | 47 | } |
38 | } | 48 | } |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index bf26048f2..e6af99035 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -254,12 +254,12 @@ impl CrateGraph { | |||
254 | return false; | 254 | return false; |
255 | } | 255 | } |
256 | 256 | ||
257 | if target == from { | ||
258 | return true; | ||
259 | } | ||
260 | |||
257 | for dep in &self[from].dependencies { | 261 | for dep in &self[from].dependencies { |
258 | let crate_id = dep.crate_id; | 262 | let crate_id = dep.crate_id; |
259 | if crate_id == target { | ||
260 | return true; | ||
261 | } | ||
262 | |||
263 | if self.dfs_find(target, crate_id, visited) { | 263 | if self.dfs_find(target, crate_id, visited) { |
264 | return true; | 264 | return true; |
265 | } | 265 | } |
@@ -369,7 +369,7 @@ mod tests { | |||
369 | use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; | 369 | use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; |
370 | 370 | ||
371 | #[test] | 371 | #[test] |
372 | fn it_should_panic_because_of_cycle_dependencies() { | 372 | fn detect_cyclic_dependency_indirect() { |
373 | let mut graph = CrateGraph::default(); | 373 | let mut graph = CrateGraph::default(); |
374 | let crate1 = graph.add_crate_root( | 374 | let crate1 = graph.add_crate_root( |
375 | FileId(1u32), | 375 | FileId(1u32), |
@@ -404,6 +404,31 @@ mod tests { | |||
404 | } | 404 | } |
405 | 405 | ||
406 | #[test] | 406 | #[test] |
407 | fn detect_cyclic_dependency_direct() { | ||
408 | let mut graph = CrateGraph::default(); | ||
409 | let crate1 = graph.add_crate_root( | ||
410 | FileId(1u32), | ||
411 | Edition2018, | ||
412 | None, | ||
413 | CfgOptions::default(), | ||
414 | Env::default(), | ||
415 | Default::default(), | ||
416 | Default::default(), | ||
417 | ); | ||
418 | let crate2 = graph.add_crate_root( | ||
419 | FileId(2u32), | ||
420 | Edition2018, | ||
421 | None, | ||
422 | CfgOptions::default(), | ||
423 | Env::default(), | ||
424 | Default::default(), | ||
425 | Default::default(), | ||
426 | ); | ||
427 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); | ||
428 | assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err()); | ||
429 | } | ||
430 | |||
431 | #[test] | ||
407 | fn it_works() { | 432 | fn it_works() { |
408 | let mut graph = CrateGraph::default(); | 433 | let mut graph = CrateGraph::default(); |
409 | let crate1 = graph.add_crate_root( | 434 | let crate1 = graph.add_crate_root( |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 1a9f6cc76..ffd5278ec 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -26,8 +26,8 @@ use hir_ty::{ | |||
26 | autoderef, | 26 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 27 | display::{HirDisplayError, HirFormatter}, |
28 | expr::ExprValidator, | 28 | expr::ExprValidator, |
29 | method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, | 29 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, |
30 | TyDefId, TypeCtor, | 30 | TraitEnvironment, Ty, TyDefId, TypeCtor, |
31 | }; | 31 | }; |
32 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 32 | use ra_db::{CrateId, CrateName, Edition, FileId}; |
33 | use ra_prof::profile; | 33 | use ra_prof::profile; |
@@ -186,6 +186,22 @@ impl ModuleDef { | |||
186 | 186 | ||
187 | module.visibility_of(db, self) | 187 | module.visibility_of(db, self) |
188 | } | 188 | } |
189 | |||
190 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
191 | match self { | ||
192 | ModuleDef::Adt(it) => Some(it.name(db)), | ||
193 | ModuleDef::Trait(it) => Some(it.name(db)), | ||
194 | ModuleDef::Function(it) => Some(it.name(db)), | ||
195 | ModuleDef::EnumVariant(it) => Some(it.name(db)), | ||
196 | ModuleDef::TypeAlias(it) => Some(it.name(db)), | ||
197 | |||
198 | ModuleDef::Module(it) => it.name(db), | ||
199 | ModuleDef::Const(it) => it.name(db), | ||
200 | ModuleDef::Static(it) => it.name(db), | ||
201 | |||
202 | ModuleDef::BuiltinType(it) => Some(it.as_name()), | ||
203 | } | ||
204 | } | ||
189 | } | 205 | } |
190 | 206 | ||
191 | pub use hir_def::{ | 207 | pub use hir_def::{ |
@@ -1359,6 +1375,27 @@ impl Type { | |||
1359 | Some(adt.into()) | 1375 | Some(adt.into()) |
1360 | } | 1376 | } |
1361 | 1377 | ||
1378 | pub fn as_dyn_trait(&self) -> Option<Trait> { | ||
1379 | self.ty.value.dyn_trait().map(Into::into) | ||
1380 | } | ||
1381 | |||
1382 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | ||
1383 | self.ty.value.impl_trait_bounds(db).map(|it| { | ||
1384 | it.into_iter() | ||
1385 | .filter_map(|pred| match pred { | ||
1386 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1387 | Some(Trait::from(trait_ref.trait_)) | ||
1388 | } | ||
1389 | _ => None, | ||
1390 | }) | ||
1391 | .collect() | ||
1392 | }) | ||
1393 | } | ||
1394 | |||
1395 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1396 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | ||
1397 | } | ||
1398 | |||
1362 | // FIXME: provide required accessors such that it becomes implementable from outside. | 1399 | // FIXME: provide required accessors such that it becomes implementable from outside. |
1363 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | 1400 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { |
1364 | match (&self.ty.value, &other.ty.value) { | 1401 | match (&self.ty.value, &other.ty.value) { |
@@ -1380,6 +1417,80 @@ impl Type { | |||
1380 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | 1417 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, |
1381 | } | 1418 | } |
1382 | } | 1419 | } |
1420 | |||
1421 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | ||
1422 | // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself. | ||
1423 | // We need a different order here. | ||
1424 | |||
1425 | fn walk_substs( | ||
1426 | db: &dyn HirDatabase, | ||
1427 | type_: &Type, | ||
1428 | substs: &Substs, | ||
1429 | cb: &mut impl FnMut(Type), | ||
1430 | ) { | ||
1431 | for ty in substs.iter() { | ||
1432 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | fn walk_bounds( | ||
1437 | db: &dyn HirDatabase, | ||
1438 | type_: &Type, | ||
1439 | bounds: &[GenericPredicate], | ||
1440 | cb: &mut impl FnMut(Type), | ||
1441 | ) { | ||
1442 | for pred in bounds { | ||
1443 | match pred { | ||
1444 | GenericPredicate::Implemented(trait_ref) => { | ||
1445 | cb(type_.clone()); | ||
1446 | walk_substs(db, type_, &trait_ref.substs, cb); | ||
1447 | } | ||
1448 | _ => (), | ||
1449 | } | ||
1450 | } | ||
1451 | } | ||
1452 | |||
1453 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | ||
1454 | let ty = type_.ty.value.strip_references(); | ||
1455 | match ty { | ||
1456 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | ||
1457 | match ctor { | ||
1458 | TypeCtor::Adt(_) => { | ||
1459 | cb(type_.derived(ty.clone())); | ||
1460 | } | ||
1461 | TypeCtor::AssociatedType(_) => { | ||
1462 | if let Some(_) = ty.associated_type_parent_trait(db) { | ||
1463 | cb(type_.derived(ty.clone())); | ||
1464 | } | ||
1465 | } | ||
1466 | _ => (), | ||
1467 | } | ||
1468 | |||
1469 | // adt params, tuples, etc... | ||
1470 | walk_substs(db, type_, parameters, cb); | ||
1471 | } | ||
1472 | Ty::Opaque(opaque_ty) => { | ||
1473 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1474 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1475 | } | ||
1476 | |||
1477 | walk_substs(db, type_, &opaque_ty.parameters, cb); | ||
1478 | } | ||
1479 | Ty::Placeholder(_) => { | ||
1480 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1481 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1482 | } | ||
1483 | } | ||
1484 | Ty::Dyn(bounds) => { | ||
1485 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | ||
1486 | } | ||
1487 | |||
1488 | _ => (), | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | walk_type(db, self, &mut cb); | ||
1493 | } | ||
1383 | } | 1494 | } |
1384 | 1495 | ||
1385 | impl HirDisplay for Type { | 1496 | impl HirDisplay for Type { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index b6b665de1..b25dac28e 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -16,7 +16,7 @@ pub use hir_expand::db::{ | |||
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, |
21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, | 21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, |
22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, | 22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index a232a5856..6a49c424a 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -6,9 +6,9 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
6 | 6 | ||
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, TraitId, | 9 | AsMacroCall, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use ra_db::{FileId, FileRange}; |
@@ -104,6 +104,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
104 | tree | 104 | tree |
105 | } | 105 | } |
106 | 106 | ||
107 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { | ||
108 | let file_id = d.source().file_id; | ||
109 | let root = self.db.parse_or_expand(file_id).unwrap(); | ||
110 | self.cache(root, file_id); | ||
111 | d.ast(self.db) | ||
112 | } | ||
113 | |||
107 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 114 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
108 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 115 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
109 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 116 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
@@ -247,6 +254,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
247 | self.analyze(path.syntax()).resolve_path(self.db, path) | 254 | self.analyze(path.syntax()).resolve_path(self.db, path) |
248 | } | 255 | } |
249 | 256 | ||
257 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { | ||
258 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | ||
259 | } | ||
260 | |||
250 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | 261 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { |
251 | let src = self.find_file(path.syntax().clone()); | 262 | let src = self.find_file(path.syntax().clone()); |
252 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) | 263 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 7c6bbea13..757d1e397 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -313,6 +313,16 @@ impl SourceAnalyzer { | |||
313 | })?; | 313 | })?; |
314 | Some(macro_call_id.as_file()) | 314 | Some(macro_call_id.as_file()) |
315 | } | 315 | } |
316 | |||
317 | pub(crate) fn resolve_variant( | ||
318 | &self, | ||
319 | db: &dyn HirDatabase, | ||
320 | record_lit: ast::RecordLit, | ||
321 | ) -> Option<VariantId> { | ||
322 | let infer = self.infer.as_ref()?; | ||
323 | let expr_id = self.expr_id(db, &record_lit.into())?; | ||
324 | infer.variant_resolution_for_expr(expr_id) | ||
325 | } | ||
316 | } | 326 | } |
317 | 327 | ||
318 | fn scope_for( | 328 | fn scope_for( |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index e48ff38f9..661f00407 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -87,15 +87,13 @@ impl ExprScopes { | |||
87 | } | 87 | } |
88 | 88 | ||
89 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { | 89 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { |
90 | match &body[pat] { | 90 | let pattern = &body[pat]; |
91 | Pat::Bind { name, .. } => { | 91 | if let Pat::Bind { name, .. } = pattern { |
92 | // bind can have a sub pattern, but it's actually not allowed | 92 | let entry = ScopeEntry { name: name.clone(), pat }; |
93 | // to bind to things in there | 93 | self.scopes[scope].entries.push(entry); |
94 | let entry = ScopeEntry { name: name.clone(), pat }; | ||
95 | self.scopes[scope].entries.push(entry) | ||
96 | } | ||
97 | p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), | ||
98 | } | 94 | } |
95 | |||
96 | pattern.walk_child_pats(|pat| self.add_bindings(body, scope, pat)); | ||
99 | } | 97 | } |
100 | 98 | ||
101 | fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { | 99 | fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { |
@@ -190,8 +188,8 @@ mod tests { | |||
190 | } | 188 | } |
191 | } | 189 | } |
192 | 190 | ||
193 | fn do_check(code: &str, expected: &[&str]) { | 191 | fn do_check(ra_fixture: &str, expected: &[&str]) { |
194 | let (off, code) = extract_offset(code); | 192 | let (off, code) = extract_offset(ra_fixture); |
195 | let code = { | 193 | let code = { |
196 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
197 | let off: usize = off.into(); | 195 | let off: usize = off.into(); |
@@ -300,6 +298,22 @@ mod tests { | |||
300 | ); | 298 | ); |
301 | } | 299 | } |
302 | 300 | ||
301 | #[test] | ||
302 | fn test_bindings_after_at() { | ||
303 | do_check( | ||
304 | r" | ||
305 | fn foo() { | ||
306 | match Some(()) { | ||
307 | opt @ Some(unit) => { | ||
308 | <|> | ||
309 | } | ||
310 | _ => {} | ||
311 | } | ||
312 | }", | ||
313 | &["opt", "unit"], | ||
314 | ); | ||
315 | } | ||
316 | |||
303 | fn do_check_local_name(code: &str, expected_offset: u32) { | 317 | fn do_check_local_name(code: &str, expected_offset: u32) { |
304 | let (off, code) = extract_offset(code); | 318 | let (off, code) = extract_offset(code); |
305 | 319 | ||
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs index 510c5e064..30db48f86 100644 --- a/crates/ra_hir_def/src/diagnostics.rs +++ b/crates/ra_hir_def/src/diagnostics.rs | |||
@@ -3,7 +3,6 @@ | |||
3 | use std::any::Any; | 3 | use std::any::Any; |
4 | 4 | ||
5 | use hir_expand::diagnostics::Diagnostic; | 5 | use hir_expand::diagnostics::Diagnostic; |
6 | use ra_db::RelativePathBuf; | ||
7 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; | 6 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; |
8 | 7 | ||
9 | use hir_expand::{HirFileId, InFile}; | 8 | use hir_expand::{HirFileId, InFile}; |
@@ -12,7 +11,7 @@ use hir_expand::{HirFileId, InFile}; | |||
12 | pub struct UnresolvedModule { | 11 | pub struct UnresolvedModule { |
13 | pub file: HirFileId, | 12 | pub file: HirFileId, |
14 | pub decl: AstPtr<ast::Module>, | 13 | pub decl: AstPtr<ast::Module>, |
15 | pub candidate: RelativePathBuf, | 14 | pub candidate: String, |
16 | } | 15 | } |
17 | 16 | ||
18 | impl Diagnostic for UnresolvedModule { | 17 | impl Diagnostic for UnresolvedModule { |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index edc59e5a8..af2a717c9 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -159,7 +159,7 @@ pub struct TypeAliasId(salsa::InternId); | |||
159 | type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>; | 159 | type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>; |
160 | impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); | 160 | impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); |
161 | 161 | ||
162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] |
163 | pub struct ImplId(salsa::InternId); | 163 | pub struct ImplId(salsa::InternId); |
164 | type ImplLoc = ItemLoc<ast::ImplDef>; | 164 | type ImplLoc = ItemLoc<ast::ImplDef>; |
165 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | 165 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index f279c2ad4..b8560fdc9 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -119,13 +119,6 @@ impl Default for ModuleOrigin { | |||
119 | } | 119 | } |
120 | 120 | ||
121 | impl ModuleOrigin { | 121 | impl ModuleOrigin { |
122 | pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self { | ||
123 | match file { | ||
124 | None => ModuleOrigin::Inline { definition: declaration }, | ||
125 | Some(definition) => ModuleOrigin::File { declaration, definition }, | ||
126 | } | ||
127 | } | ||
128 | |||
129 | fn declaration(&self) -> Option<AstId<ast::Module>> { | 122 | fn declaration(&self) -> Option<AstId<ast::Module>> { |
130 | match self { | 123 | match self { |
131 | ModuleOrigin::File { declaration: module, .. } | 124 | ModuleOrigin::File { declaration: module, .. } |
@@ -296,7 +289,6 @@ pub enum ModuleSource { | |||
296 | 289 | ||
297 | mod diagnostics { | 290 | mod diagnostics { |
298 | use hir_expand::diagnostics::DiagnosticSink; | 291 | use hir_expand::diagnostics::DiagnosticSink; |
299 | use ra_db::RelativePathBuf; | ||
300 | use ra_syntax::{ast, AstPtr}; | 292 | use ra_syntax::{ast, AstPtr}; |
301 | 293 | ||
302 | use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId}; | 294 | use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId}; |
@@ -306,7 +298,7 @@ mod diagnostics { | |||
306 | UnresolvedModule { | 298 | UnresolvedModule { |
307 | module: LocalModuleId, | 299 | module: LocalModuleId, |
308 | declaration: AstId<ast::Module>, | 300 | declaration: AstId<ast::Module>, |
309 | candidate: RelativePathBuf, | 301 | candidate: String, |
310 | }, | 302 | }, |
311 | } | 303 | } |
312 | 304 | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 976e5e585..b8f6aac8f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -36,8 +36,8 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
36 | 36 | ||
37 | // populate external prelude | 37 | // populate external prelude |
38 | for dep in &crate_graph[def_map.krate].dependencies { | 38 | for dep in &crate_graph[def_map.krate].dependencies { |
39 | let dep_def_map = db.crate_def_map(dep.crate_id); | ||
40 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); | 39 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); |
40 | let dep_def_map = db.crate_def_map(dep.crate_id); | ||
41 | def_map.extern_prelude.insert( | 41 | def_map.extern_prelude.insert( |
42 | dep.as_name(), | 42 | dep.as_name(), |
43 | ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), | 43 | ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), |
@@ -825,7 +825,10 @@ impl ModCollector<'_, '_> { | |||
825 | let modules = &mut self.def_collector.def_map.modules; | 825 | let modules = &mut self.def_collector.def_map.modules; |
826 | let res = modules.alloc(ModuleData::default()); | 826 | let res = modules.alloc(ModuleData::default()); |
827 | modules[res].parent = Some(self.module_id); | 827 | modules[res].parent = Some(self.module_id); |
828 | modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); | 828 | modules[res].origin = match definition { |
829 | None => ModuleOrigin::Inline { definition: declaration }, | ||
830 | Some(definition) => ModuleOrigin::File { declaration, definition }, | ||
831 | }; | ||
829 | for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { | 832 | for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { |
830 | modules[res].scope.define_legacy_macro(name, mac) | 833 | modules[res].scope.define_legacy_macro(name, mac) |
831 | } | 834 | } |
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs index cede4a6fc..19fe0615a 100644 --- a/crates/ra_hir_def/src/nameres/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs | |||
@@ -44,7 +44,7 @@ impl ModDir { | |||
44 | file_id: HirFileId, | 44 | file_id: HirFileId, |
45 | name: &Name, | 45 | name: &Name, |
46 | attr_path: Option<&SmolStr>, | 46 | attr_path: Option<&SmolStr>, |
47 | ) -> Result<(FileId, ModDir), RelativePathBuf> { | 47 | ) -> Result<(FileId, ModDir), String> { |
48 | let file_id = file_id.original_file(db.upcast()); | 48 | let file_id = file_id.original_file(db.upcast()); |
49 | 49 | ||
50 | let mut candidate_files = Vec::new(); | 50 | let mut candidate_files = Vec::new(); |
@@ -52,11 +52,11 @@ impl ModDir { | |||
52 | Some(attr_path) => { | 52 | Some(attr_path) => { |
53 | let base = | 53 | let base = |
54 | if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path }; | 54 | if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path }; |
55 | candidate_files.push(base.join(attr_path)) | 55 | candidate_files.push(base.join(attr_path).to_string()) |
56 | } | 56 | } |
57 | None => { | 57 | None => { |
58 | candidate_files.push(self.path.join(&format!("{}.rs", name))); | 58 | candidate_files.push(self.path.join(&format!("{}.rs", name)).to_string()); |
59 | candidate_files.push(self.path.join(&format!("{}/mod.rs", name))); | 59 | candidate_files.push(self.path.join(&format!("{}/mod.rs", name)).to_string()); |
60 | } | 60 | } |
61 | }; | 61 | }; |
62 | 62 | ||
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 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use 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 | }; |
9 | use ra_arena::map::ArenaMap; | 9 | use ra_arena::map::ArenaMap; |
10 | use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; | 10 | use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | 12 | ||
13 | use crate::{ |