diff options
96 files changed, 3770 insertions, 1442 deletions
diff --git a/Cargo.lock b/Cargo.lock index dbd7a746e..e8f10b938 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -13,9 +13,9 @@ dependencies = [ | |||
13 | 13 | ||
14 | [[package]] | 14 | [[package]] |
15 | name = "adler" | 15 | name = "adler" |
16 | version = "1.0.1" | 16 | version = "1.0.2" |
17 | source = "registry+https://github.com/rust-lang/crates.io-index" | 17 | source = "registry+https://github.com/rust-lang/crates.io-index" |
18 | checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093" | 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" |
19 | 19 | ||
20 | [[package]] | 20 | [[package]] |
21 | name = "always-assert" | 21 | name = "always-assert" |
@@ -112,6 +112,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
112 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" | 112 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" |
113 | 113 | ||
114 | [[package]] | 114 | [[package]] |
115 | name = "camino" | ||
116 | version = "1.0.1" | ||
117 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
118 | checksum = "9bb47ab72bdba43021afa16dc1ef4d80c980d366b17ed37ea8d2ebe2087075b9" | ||
119 | dependencies = [ | ||
120 | "serde", | ||
121 | ] | ||
122 | |||
123 | [[package]] | ||
115 | name = "cargo-platform" | 124 | name = "cargo-platform" |
116 | version = "0.1.1" | 125 | version = "0.1.1" |
117 | source = "registry+https://github.com/rust-lang/crates.io-index" | 126 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -122,10 +131,11 @@ dependencies = [ | |||
122 | 131 | ||
123 | [[package]] | 132 | [[package]] |
124 | name = "cargo_metadata" | 133 | name = "cargo_metadata" |
125 | version = "0.12.3" | 134 | version = "0.13.1" |
126 | source = "registry+https://github.com/rust-lang/crates.io-index" | 135 | source = "registry+https://github.com/rust-lang/crates.io-index" |
127 | checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" | 136 | checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8" |
128 | dependencies = [ | 137 | dependencies = [ |
138 | "camino", | ||
129 | "cargo-platform", | 139 | "cargo-platform", |
130 | "semver", | 140 | "semver", |
131 | "semver-parser", | 141 | "semver-parser", |
@@ -158,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
158 | 168 | ||
159 | [[package]] | 169 | [[package]] |
160 | name = "chalk-derive" | 170 | name = "chalk-derive" |
161 | version = "0.58.0" | 171 | version = "0.59.0" |
162 | source = "registry+https://github.com/rust-lang/crates.io-index" | 172 | source = "registry+https://github.com/rust-lang/crates.io-index" |
163 | checksum = "e625b7c688272783140509a0de8f7aa9000217cb0982c9b10606a12b0b747ba8" | 173 | checksum = "4b9000fbcb67353dc8973ab9fd136277d321d85b79bd36b8756bb3ae0979a94a" |
164 | dependencies = [ | 174 | dependencies = [ |
165 | "proc-macro2", | 175 | "proc-macro2", |
166 | "quote", | 176 | "quote", |
@@ -170,9 +180,9 @@ dependencies = [ | |||
170 | 180 | ||
171 | [[package]] | 181 | [[package]] |
172 | name = "chalk-ir" | 182 | name = "chalk-ir" |
173 | version = "0.58.0" | 183 | version = "0.59.0" |
174 | source = "registry+https://github.com/rust-lang/crates.io-index" | 184 | source = "registry+https://github.com/rust-lang/crates.io-index" |
175 | checksum = "c220d870128959d7d56667060d556ffdebd490f32ee0fc9f4060a76c1193f206" | 185 | checksum = "b23528d61b3557c676eccf508fa0771a38453b379f0b780154eaa7f70afe8dfc" |
176 | dependencies = [ | 186 | dependencies = [ |
177 | "bitflags", | 187 | "bitflags", |
178 | "chalk-derive", | 188 | "chalk-derive", |
@@ -181,9 +191,9 @@ dependencies = [ | |||
181 | 191 | ||
182 | [[package]] | 192 | [[package]] |
183 | name = "chalk-recursive" | 193 | name = "chalk-recursive" |
184 | version = "0.58.0" | 194 | version = "0.59.0" |
185 | source = "registry+https://github.com/rust-lang/crates.io-index" | 195 | source = "registry+https://github.com/rust-lang/crates.io-index" |
186 | checksum = "7d8cd81a15aa936215378e695a8907b9f1af8626a27a32ee22e97a50984960da" | 196 | checksum = "a8bdd37afc666b771de8b4429fe014363d0e74aae5cc26f320f60a3eab34d744" |
187 | dependencies = [ | 197 | dependencies = [ |
188 | "chalk-derive", | 198 | "chalk-derive", |
189 | "chalk-ir", | 199 | "chalk-ir", |
@@ -194,14 +204,14 @@ dependencies = [ | |||
194 | 204 | ||
195 | [[package]] | 205 | [[package]] |
196 | name = "chalk-solve" | 206 | name = "chalk-solve" |
197 | version = "0.58.0" | 207 | version = "0.59.0" |
198 | source = "registry+https://github.com/rust-lang/crates.io-index" | 208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
199 | checksum = "55571250dfe096a4c899be88c81418284c952ce1c8a06aa16afb5781b298e9c9" | 209 | checksum = "4182c42ca319cb71c89898ebc3d2671d1fa7d928123b171b66f1797a2000b9c8" |
200 | dependencies = [ | 210 | dependencies = [ |
201 | "chalk-derive", | 211 | "chalk-derive", |
202 | "chalk-ir", | 212 | "chalk-ir", |
203 | "ena", | 213 | "ena", |
204 | "itertools 0.9.0", | 214 | "itertools", |
205 | "petgraph", | 215 | "petgraph", |
206 | "rustc-hash", | 216 | "rustc-hash", |
207 | "tracing", | 217 | "tracing", |
@@ -475,7 +485,7 @@ dependencies = [ | |||
475 | "hir_def", | 485 | "hir_def", |
476 | "hir_expand", | 486 | "hir_expand", |
477 | "hir_ty", | 487 | "hir_ty", |
478 | "itertools 0.10.0", | 488 | "itertools", |
479 | "log", | 489 | "log", |
480 | "profile", | 490 | "profile", |
481 | "rustc-hash", | 491 | "rustc-hash", |
@@ -497,7 +507,7 @@ dependencies = [ | |||
497 | "fst", | 507 | "fst", |
498 | "hir_expand", | 508 | "hir_expand", |
499 | "indexmap", | 509 | "indexmap", |
500 | "itertools 0.10.0", | 510 | "itertools", |
501 | "la-arena", | 511 | "la-arena", |
502 | "log", | 512 | "log", |
503 | "mbe", | 513 | "mbe", |
@@ -541,7 +551,7 @@ dependencies = [ | |||
541 | "expect-test", | 551 | "expect-test", |
542 | "hir_def", | 552 | "hir_def", |
543 | "hir_expand", | 553 | "hir_expand", |
544 | "itertools 0.10.0", | 554 | "itertools", |
545 | "la-arena", | 555 | "la-arena", |
546 | "log", | 556 | "log", |
547 | "once_cell", | 557 | "once_cell", |
@@ -579,7 +589,7 @@ dependencies = [ | |||
579 | "ide_db", | 589 | "ide_db", |
580 | "ide_ssr", | 590 | "ide_ssr", |
581 | "indexmap", | 591 | "indexmap", |
582 | "itertools 0.10.0", | 592 | "itertools", |
583 | "log", | 593 | "log", |
584 | "oorandom", | 594 | "oorandom", |
585 | "profile", | 595 | "profile", |
@@ -601,7 +611,7 @@ dependencies = [ | |||
601 | "expect-test", | 611 | "expect-test", |
602 | "hir", | 612 | "hir", |
603 | "ide_db", | 613 | "ide_db", |
604 | "itertools 0.10.0", | 614 | "itertools", |
605 | "profile", | 615 | "profile", |
606 | "rustc-hash", | 616 | "rustc-hash", |
607 | "stdx", | 617 | "stdx", |
@@ -619,7 +629,7 @@ dependencies = [ | |||
619 | "expect-test", | 629 | "expect-test", |
620 | "hir", | 630 | "hir", |
621 | "ide_db", | 631 | "ide_db", |
622 | "itertools 0.10.0", | 632 | "itertools", |
623 | "log", | 633 | "log", |
624 | "profile", | 634 | "profile", |
625 | "rustc-hash", | 635 | "rustc-hash", |
@@ -638,7 +648,7 @@ dependencies = [ | |||
638 | "expect-test", | 648 | "expect-test", |
639 | "fst", | 649 | "fst", |
640 | "hir", | 650 | "hir", |
641 | "itertools 0.10.0", | 651 | "itertools", |
642 | "log", | 652 | "log", |
643 | "once_cell", | 653 | "once_cell", |
644 | "profile", | 654 | "profile", |
@@ -657,7 +667,7 @@ dependencies = [ | |||
657 | "expect-test", | 667 | "expect-test", |
658 | "hir", | 668 | "hir", |
659 | "ide_db", | 669 | "ide_db", |
660 | "itertools 0.10.0", | 670 | "itertools", |
661 | "rustc-hash", | 671 | "rustc-hash", |
662 | "syntax", | 672 | "syntax", |
663 | "test_utils", | 673 | "test_utils", |
@@ -716,15 +726,6 @@ dependencies = [ | |||
716 | 726 | ||
717 | [[package]] | 727 | [[package]] |
718 | name = "itertools" | 728 | name = "itertools" |
719 | version = "0.9.0" | ||
720 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
721 | checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" | ||
722 | dependencies = [ | ||
723 | "either", | ||
724 | ] | ||
725 | |||
726 | [[package]] | ||
727 | name = "itertools" | ||
728 | version = "0.10.0" | 729 | version = "0.10.0" |
729 | source = "registry+https://github.com/rust-lang/crates.io-index" | 730 | source = "registry+https://github.com/rust-lang/crates.io-index" |
730 | checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" | 731 | checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" |
@@ -788,9 +789,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
788 | 789 | ||
789 | [[package]] | 790 | [[package]] |
790 | name = "libc" | 791 | name = "libc" |
791 | version = "0.2.86" | 792 | version = "0.2.87" |
792 | source = "registry+https://github.com/rust-lang/crates.io-index" | 793 | source = "registry+https://github.com/rust-lang/crates.io-index" |
793 | checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" | 794 | checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" |
794 | 795 | ||
795 | [[package]] | 796 | [[package]] |
796 | name = "libloading" | 797 | name = "libloading" |
@@ -878,6 +879,7 @@ dependencies = [ | |||
878 | "profile", | 879 | "profile", |
879 | "rustc-hash", | 880 | "rustc-hash", |
880 | "smallvec", | 881 | "smallvec", |
882 | "stdx", | ||
881 | "syntax", | 883 | "syntax", |
882 | "test_utils", | 884 | "test_utils", |
883 | "tt", | 885 | "tt", |
@@ -1014,9 +1016,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" | |||
1014 | 1016 | ||
1015 | [[package]] | 1017 | [[package]] |
1016 | name = "once_cell" | 1018 | name = "once_cell" |
1017 | version = "1.7.0" | 1019 | version = "1.7.2" |
1018 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1019 | checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a" | 1021 | checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" |
1020 | 1022 | ||
1021 | [[package]] | 1023 | [[package]] |
1022 | name = "oorandom" | 1024 | name = "oorandom" |
@@ -1124,16 +1126,10 @@ dependencies = [ | |||
1124 | ] | 1126 | ] |
1125 | 1127 | ||
1126 | [[package]] | 1128 | [[package]] |
1127 | name = "pico-args" | ||
1128 | version = "0.4.0" | ||
1129 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1130 | checksum = "d70072c20945e1ab871c472a285fc772aefd4f5407723c206242f2c6f94595d6" | ||
1131 | |||
1132 | [[package]] | ||
1133 | name = "pin-project-lite" | 1129 | name = "pin-project-lite" |
1134 | version = "0.2.4" | 1130 | version = "0.2.5" |
1135 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1136 | checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" | 1132 | checksum = "0cf491442e4b033ed1c722cb9f0df5fcfcf4de682466c46469c36bc47dc5548a" |
1137 | 1133 | ||
1138 | [[package]] | 1134 | [[package]] |
1139 | name = "proc-macro-hack" | 1135 | name = "proc-macro-hack" |
@@ -1206,7 +1202,7 @@ dependencies = [ | |||
1206 | "base_db", | 1202 | "base_db", |
1207 | "cargo_metadata", | 1203 | "cargo_metadata", |
1208 | "cfg", | 1204 | "cfg", |
1209 | "itertools 0.10.0", | 1205 | "itertools", |
1210 | "la-arena", | 1206 | "la-arena", |
1211 | "log", | 1207 | "log", |
1212 | "paths", | 1208 | "paths", |
@@ -1338,7 +1334,7 @@ dependencies = [ | |||
1338 | "ide", | 1334 | "ide", |
1339 | "ide_db", | 1335 | "ide_db", |
1340 | "ide_ssr", | 1336 | "ide_ssr", |
1341 | "itertools 0.10.0", | 1337 | "itertools", |
1342 | "jemallocator", | 1338 | "jemallocator", |
1343 | "jod-thread", | 1339 | "jod-thread", |
1344 | "log", | 1340 | "log", |
@@ -1348,7 +1344,6 @@ dependencies = [ | |||
1348 | "mimalloc", | 1344 | "mimalloc", |
1349 | "oorandom", | 1345 | "oorandom", |
1350 | "parking_lot", | 1346 | "parking_lot", |
1351 | "pico-args", | ||
1352 | "proc_macro_srv", | 1347 | "proc_macro_srv", |
1353 | "profile", | 1348 | "profile", |
1354 | "project_model", | 1349 | "project_model", |
@@ -1370,13 +1365,14 @@ dependencies = [ | |||
1370 | "vfs", | 1365 | "vfs", |
1371 | "vfs-notify", | 1366 | "vfs-notify", |
1372 | "winapi", | 1367 | "winapi", |
1368 | "xflags", | ||
1373 | ] | 1369 | ] |
1374 | 1370 | ||
1375 | [[package]] | 1371 | [[package]] |
1376 | name = "rustc-ap-rustc_lexer" | 1372 | name = "rustc-ap-rustc_lexer" |
1377 | version = "708.0.0" | 1373 | version = "709.0.0" |
1378 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1379 | checksum = "2706fc7106c75eaea49efe9f35f719a6fdfdb95212122ec2b543659406bae7ea" | 1375 | checksum = "f69f83314702aaccf29c7401cc63bb0d9fa7869a185a23b8379f08c91514b3f3" |
1380 | dependencies = [ | 1376 | dependencies = [ |
1381 | "unicode-xid", | 1377 | "unicode-xid", |
1382 | ] | 1378 | ] |
@@ -1490,9 +1486,9 @@ dependencies = [ | |||
1490 | 1486 | ||
1491 | [[package]] | 1487 | [[package]] |
1492 | name = "serde_json" | 1488 | name = "serde_json" |
1493 | version = "1.0.62" | 1489 | version = "1.0.64" |
1494 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1495 | checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" | 1491 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" |
1496 | dependencies = [ | 1492 | dependencies = [ |
1497 | "indexmap", | 1493 | "indexmap", |
1498 | "itoa", | 1494 | "itoa", |
@@ -1593,7 +1589,7 @@ dependencies = [ | |||
1593 | "arrayvec", | 1589 | "arrayvec", |
1594 | "expect-test", | 1590 | "expect-test", |
1595 | "indexmap", | 1591 | "indexmap", |
1596 | "itertools 0.10.0", | 1592 | "itertools", |
1597 | "once_cell", | 1593 | "once_cell", |
1598 | "parser", | 1594 | "parser", |
1599 | "profile", | 1595 | "profile", |
@@ -1922,19 +1918,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1922 | checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" | 1918 | checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" |
1923 | 1919 | ||
1924 | [[package]] | 1920 | [[package]] |
1921 | name = "xflags" | ||
1922 | version = "0.1.4" | ||
1923 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1924 | checksum = "222e914b43cec5d7305ac5116d10a14b3a52c50e9062d642c92631f3beabc729" | ||
1925 | dependencies = [ | ||
1926 | "xflags-macros", | ||
1927 | ] | ||
1928 | |||
1929 | [[package]] | ||
1930 | name = "xflags-macros" | ||
1931 | version = "0.1.4" | ||
1932 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1933 | checksum = "52f18f5b4aa7f95e209d5b9274f6164c3938920b4d5c75f97f0dd16daee25ddd" | ||
1934 | dependencies = [ | ||
1935 | "proc-macro2", | ||
1936 | ] | ||
1937 | |||
1938 | [[package]] | ||
1925 | name = "xshell" | 1939 | name = "xshell" |
1926 | version = "0.1.8" | 1940 | version = "0.1.9" |
1927 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1928 | checksum = "ed373ede30cea03e8c0af22f48ee1ba80efbf06fec8b4746977e6ee703878de0" | 1942 | checksum = "6f18102278453c8f70ea5c514ac78cb4c73a0ef72a8273d17094b52f9584c0c1" |
1929 | dependencies = [ | 1943 | dependencies = [ |
1930 | "xshell-macros", | 1944 | "xshell-macros", |
1931 | ] | 1945 | ] |
1932 | 1946 | ||
1933 | [[package]] | 1947 | [[package]] |
1934 | name = "xshell-macros" | 1948 | name = "xshell-macros" |
1935 | version = "0.1.8" | 1949 | version = "0.1.9" |
1936 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1950 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1937 | checksum = "7f6af9f8119104697b0105989a73c578ce33f922d9d6f3dae0e8ae3d538db321" | 1951 | checksum = "6093c460064572007f885facc70bb0ca5e40a83ea7ff8b16c1abbee56fd2e767" |
1938 | 1952 | ||
1939 | [[package]] | 1953 | [[package]] |
1940 | name = "xtask" | 1954 | name = "xtask" |
@@ -1942,11 +1956,11 @@ version = "0.1.0" | |||
1942 | dependencies = [ | 1956 | dependencies = [ |
1943 | "anyhow", | 1957 | "anyhow", |
1944 | "flate2", | 1958 | "flate2", |
1945 | "pico-args", | ||
1946 | "proc-macro2", | 1959 | "proc-macro2", |
1947 | "quote", | 1960 | "quote", |
1948 | "ungrammar", | 1961 | "ungrammar", |
1949 | "walkdir", | 1962 | "walkdir", |
1950 | "write-json", | 1963 | "write-json", |
1964 | "xflags", | ||
1951 | "xshell", | 1965 | "xshell", |
1952 | ] | 1966 | ] |
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml index 1d19c7886..2a1a21b28 100644 --- a/crates/flycheck/Cargo.toml +++ b/crates/flycheck/Cargo.toml | |||
@@ -12,9 +12,9 @@ doctest = false | |||
12 | [dependencies] | 12 | [dependencies] |
13 | crossbeam-channel = "0.5.0" | 13 | crossbeam-channel = "0.5.0" |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | cargo_metadata = "0.12.2" | 15 | cargo_metadata = "0.13" |
16 | serde_json = "1.0.48" | 16 | serde_json = "1.0.48" |
17 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
18 | 18 | ||
19 | toolchain = { path = "../toolchain", version = "0.0.0" } | 19 | toolchain = { path = "../toolchain", version = "0.0.0" } |
20 | stdx = { path = "../stdx", version = "0.0.0" } | 20 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index e04208006..e2a59497a 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs | |||
@@ -194,7 +194,7 @@ impl FlycheckActor { | |||
194 | cargo_metadata::Message::BuildScriptExecuted(_) | 194 | cargo_metadata::Message::BuildScriptExecuted(_) |
195 | | cargo_metadata::Message::BuildFinished(_) | 195 | | cargo_metadata::Message::BuildFinished(_) |
196 | | cargo_metadata::Message::TextLine(_) | 196 | | cargo_metadata::Message::TextLine(_) |
197 | | cargo_metadata::Message::Unknown => {} | 197 | | _ => {} |
198 | }, | 198 | }, |
199 | } | 199 | } |
200 | } | 200 | } |
@@ -329,8 +329,7 @@ impl CargoActor { | |||
329 | // Skip certain kinds of messages to only spend time on what's useful | 329 | // Skip certain kinds of messages to only spend time on what's useful |
330 | match &message { | 330 | match &message { |
331 | cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), | 331 | cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), |
332 | cargo_metadata::Message::BuildScriptExecuted(_) | 332 | cargo_metadata::Message::BuildScriptExecuted(_) => (), |
333 | | cargo_metadata::Message::Unknown => (), | ||
334 | _ => self.sender.send(message).unwrap(), | 333 | _ => self.sender.send(message).unwrap(), |
335 | } | 334 | } |
336 | } | 335 | } |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 00b0dc082..7656db974 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -14,7 +14,7 @@ use hir_def::{ | |||
14 | per_ns::PerNs, | 14 | per_ns::PerNs, |
15 | resolver::{HasResolver, Resolver}, | 15 | resolver::{HasResolver, Resolver}, |
16 | src::HasSource as _, | 16 | src::HasSource as _, |
17 | type_ref::{Mutability, TypeRef}, | 17 | type_ref::TypeRef, |
18 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | 18 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, |
19 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | 19 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, |
20 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 20 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, |
@@ -32,8 +32,8 @@ use hir_ty::{ | |||
32 | method_resolution, | 32 | method_resolution, |
33 | traits::{FnTrait, Solution, SolutionVariables}, | 33 | traits::{FnTrait, Solution, SolutionVariables}, |
34 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, | 34 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, |
35 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, | 35 | InEnvironment, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, |
36 | Ty, TyDefId, TyVariableKind, | 36 | TraitEnvironment, Ty, TyDefId, TyVariableKind, |
37 | }; | 37 | }; |
38 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::{format_to, impl_from}; | 39 | use stdx::{format_to, impl_from}; |
@@ -836,7 +836,7 @@ pub enum Access { | |||
836 | impl From<Mutability> for Access { | 836 | impl From<Mutability> for Access { |
837 | fn from(mutability: Mutability) -> Access { | 837 | fn from(mutability: Mutability) -> Access { |
838 | match mutability { | 838 | match mutability { |
839 | Mutability::Shared => Access::Shared, | 839 | Mutability::Not => Access::Shared, |
840 | Mutability::Mut => Access::Exclusive, | 840 | Mutability::Mut => Access::Exclusive, |
841 | } | 841 | } |
842 | } | 842 | } |
@@ -865,7 +865,10 @@ impl SelfParam { | |||
865 | .params | 865 | .params |
866 | .first() | 866 | .first() |
867 | .map(|param| match *param { | 867 | .map(|param| match *param { |
868 | TypeRef::Reference(.., mutability) => mutability.into(), | 868 | TypeRef::Reference(.., mutability) => match mutability { |
869 | hir_def::type_ref::Mutability::Shared => Access::Shared, | ||
870 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, | ||
871 | }, | ||
869 | _ => Access::Owned, | 872 | _ => Access::Owned, |
870 | }) | 873 | }) |
871 | .unwrap_or(Access::Owned) | 874 | .unwrap_or(Access::Owned) |
@@ -1697,7 +1700,7 @@ impl Type { | |||
1697 | 1700 | ||
1698 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1701 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1699 | let adt_id = match self.ty.value { | 1702 | let adt_id = match self.ty.value { |
1700 | Ty::Adt(adt_id, ..) => adt_id, | 1703 | Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1701 | _ => return false, | 1704 | _ => return false, |
1702 | }; | 1705 | }; |
1703 | 1706 | ||
@@ -1725,8 +1728,8 @@ impl Type { | |||
1725 | 1728 | ||
1726 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1729 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1727 | let (variant_id, substs) = match self.ty.value { | 1730 | let (variant_id, substs) = match self.ty.value { |
1728 | Ty::Adt(AdtId::StructId(s), ref substs) => (s.into(), substs), | 1731 | Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1729 | Ty::Adt(AdtId::UnionId(u), ref substs) => (u.into(), substs), | 1732 | Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1730 | _ => return Vec::new(), | 1733 | _ => return Vec::new(), |
1731 | }; | 1734 | }; |
1732 | 1735 | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 769945c47..69fcdab07 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -33,11 +33,11 @@ mod has_source; | |||
33 | pub use crate::{ | 33 | pub use crate::{ |
34 | attrs::{HasAttrs, Namespace}, | 34 | attrs::{HasAttrs, Namespace}, |
35 | code_model::{ | 35 | code_model::{ |
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | 36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, BuiltinType, Callable, |
37 | ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, | 37 | CallableKind, Const, ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, |
38 | GenericDef, GenericParam, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, | 38 | FieldSource, Function, GenericDef, GenericParam, HasVisibility, Impl, Label, LifetimeParam, |
39 | Module, ModuleDef, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, | 39 | Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, Trait, Type, TypeAlias, |
40 | Variant, VariantDef, | 40 | TypeParam, Union, Variant, VariantDef, |
41 | }, | 41 | }, |
42 | has_source::HasSource, | 42 | has_source::HasSource, |
43 | semantics::{PathResolution, Semantics, SemanticsScope}, | 43 | semantics::{PathResolution, Semantics, SemanticsScope}, |
@@ -47,7 +47,6 @@ pub use hir_def::{ | |||
47 | adt::StructKind, | 47 | adt::StructKind, |
48 | attr::{Attrs, Documentation}, | 48 | attr::{Attrs, Documentation}, |
49 | body::scope::ExprScopes, | 49 | body::scope::ExprScopes, |
50 | builtin_type::BuiltinType, | ||
51 | find_path::PrefixKind, | 50 | find_path::PrefixKind, |
52 | import_map, | 51 | import_map, |
53 | item_scope::ItemInNs, | 52 | item_scope::ItemInNs, |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index fe4c3fa28..24ffa6c3a 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -367,7 +367,7 @@ fn inner_attributes( | |||
367 | // Excerpt from the reference: | 367 | // Excerpt from the reference: |
368 | // Block expressions accept outer and inner attributes, but only when they are the outer | 368 | // Block expressions accept outer and inner attributes, but only when they are the outer |
369 | // expression of an expression statement or the final expression of another block expression. | 369 | // expression of an expression statement or the final expression of another block expression. |
370 | ast::BlockExpr(it) => return None, | 370 | ast::BlockExpr(_it) => return None, |
371 | _ => return None, | 371 | _ => return None, |
372 | } | 372 | } |
373 | }; | 373 | }; |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 5e2a711b8..3a98ffbaa 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! An algorithm to find a path to refer to a certain item. | 1 | //! An algorithm to find a path to refer to a certain item. |
2 | 2 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
4 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | 7 | use test_utils::mark; |
@@ -95,7 +97,7 @@ fn find_path_inner( | |||
95 | item: ItemInNs, | 97 | item: ItemInNs, |
96 | from: ModuleId, | 98 | from: ModuleId, |
97 | max_len: usize, | 99 | max_len: usize, |
98 | prefixed: Option<PrefixKind>, | 100 | mut prefixed: Option<PrefixKind>, |
99 | ) -> Option<ModPath> { | 101 | ) -> Option<ModPath> { |
100 | if max_len == 0 { | 102 | if max_len == 0 { |
101 | return None; | 103 | return None; |
@@ -114,8 +116,9 @@ fn find_path_inner( | |||
114 | } | 116 | } |
115 | 117 | ||
116 | // - if the item is the crate root, return `crate` | 118 | // - if the item is the crate root, return `crate` |
117 | let root = def_map.module_id(def_map.root()); | 119 | let root = def_map.crate_root(db); |
118 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { | 120 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { |
121 | // FIXME: the `block_id()` check should be unnecessary, but affects the result | ||
119 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 122 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
120 | } | 123 | } |
121 | 124 | ||
@@ -165,7 +168,7 @@ fn find_path_inner( | |||
165 | 168 | ||
166 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 169 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
167 | 170 | ||
168 | let crate_root = def_map.module_id(def_map.root()); | 171 | let crate_root = def_map.crate_root(db); |
169 | let crate_attrs = db.attrs(crate_root.into()); | 172 | let crate_attrs = db.attrs(crate_root.into()); |
170 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 173 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
171 | let mut best_path = None; | 174 | let mut best_path = None; |
@@ -228,12 +231,16 @@ fn find_path_inner( | |||
228 | } | 231 | } |
229 | } | 232 | } |
230 | 233 | ||
231 | if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) { | 234 | // If the item is declared inside a block expression, don't use a prefix, as we don't handle |
232 | if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() { | 235 | // that correctly (FIXME). |
233 | // Inner items cannot be referred to via `crate::` or `self::` paths. | 236 | if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) { |
234 | prefix = PathKind::Plain; | 237 | if item_module.def_map(db).block_id().is_some() && prefixed.is_some() { |
238 | mark::hit!(prefixed_in_block_expression); | ||
239 | prefixed = Some(PrefixKind::Plain); | ||
235 | } | 240 | } |
241 | } | ||
236 | 242 | ||
243 | if let Some(prefix) = prefixed.map(PrefixKind::prefix) { | ||
237 | best_path.or_else(|| { | 244 | best_path.or_else(|| { |
238 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) | 245 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) |
239 | }) | 246 | }) |
@@ -285,12 +292,12 @@ fn find_local_import_locations( | |||
285 | let data = &def_map[from.local_id]; | 292 | let data = &def_map[from.local_id]; |
286 | let mut worklist = | 293 | let mut worklist = |
287 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); | 294 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
288 | let mut parent = data.parent; | 295 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { |
289 | while let Some(p) = parent { | 296 | worklist.push(ancestor); |
290 | worklist.push(def_map.module_id(p)); | ||
291 | parent = def_map[p].parent; | ||
292 | } | 297 | } |
293 | 298 | ||
299 | let def_map = def_map.crate_root(db).def_map(db); | ||
300 | |||
294 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 301 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
295 | 302 | ||
296 | let mut locations = Vec::new(); | 303 | let mut locations = Vec::new(); |
@@ -301,7 +308,14 @@ fn find_local_import_locations( | |||
301 | 308 | ||
302 | let ext_def_map; | 309 | let ext_def_map; |
303 | let data = if module.krate == from.krate { | 310 | let data = if module.krate == from.krate { |
304 | &def_map[module.local_id] | 311 | if module.block.is_some() { |
312 | // Re-query the block's DefMap | ||
313 | ext_def_map = module.def_map(db); | ||
314 | &ext_def_map[module.local_id] | ||
315 | } else { | ||
316 | // Reuse the root DefMap | ||
317 | &def_map[module.local_id] | ||
318 | } | ||
305 | } else { | 319 | } else { |
306 | // The crate might reexport a module defined in another crate. | 320 | // The crate might reexport a module defined in another crate. |
307 | ext_def_map = module.def_map(db); | 321 | ext_def_map = module.def_map(db); |
@@ -828,6 +842,7 @@ mod tests { | |||
828 | 842 | ||
829 | #[test] | 843 | #[test] |
830 | fn inner_items_from_inner_module() { | 844 | fn inner_items_from_inner_module() { |
845 | mark::check!(prefixed_in_block_expression); | ||
831 | check_found_path( | 846 | check_found_path( |
832 | r#" | 847 | r#" |
833 | fn main() { | 848 | fn main() { |
@@ -847,26 +862,22 @@ mod tests { | |||
847 | } | 862 | } |
848 | 863 | ||
849 | #[test] | 864 | #[test] |
850 | #[ignore] | 865 | fn outer_items_with_inner_items_present() { |
851 | fn inner_items_from_parent_module() { | ||
852 | // FIXME: ItemTree currently associates all inner items with `main`. Luckily, this sort of | ||
853 | // code is very rare, so this isn't terrible. | ||
854 | // To fix it, we should probably build dedicated `ItemTree`s for inner items, and not store | ||
855 | // them in the file's main ItemTree. This would also allow us to stop parsing function | ||
856 | // bodies when we only want to compute the crate's main DefMap. | ||
857 | check_found_path( | 866 | check_found_path( |
858 | r#" | 867 | r#" |
868 | mod module { | ||
869 | pub struct CompleteMe; | ||
870 | } | ||
871 | |||
859 | fn main() { | 872 | fn main() { |
860 | struct Struct {} | 873 | fn inner() {} |
861 | mod module { | 874 | $0 |
862 | $0 | ||
863 | } | ||
864 | } | 875 | } |
865 | "#, | 876 | "#, |
866 | "super::Struct", | 877 | "module::CompleteMe", |
867 | "super::Struct", | 878 | "module::CompleteMe", |
868 | "super::Struct", | 879 | "crate::module::CompleteMe", |
869 | "super::Struct", | 880 | "self::module::CompleteMe", |
870 | ); | 881 | ) |
871 | } | 882 | } |
872 | } | 883 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index ee46c3330..4e5daa2ff 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -12,8 +12,8 @@ use stdx::format_to; | |||
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, | 16 | LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #[derive(Copy, Clone)] | 19 | #[derive(Copy, Clone)] |
@@ -375,19 +375,9 @@ impl ItemInNs { | |||
375 | 375 | ||
376 | /// Returns the crate defining this item (or `None` if `self` is built-in). | 376 | /// Returns the crate defining this item (or `None` if `self` is built-in). |
377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | 377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { |
378 | Some(match self { | 378 | match self { |
379 | ItemInNs::Types(did) | ItemInNs::Values(did) => match did { | 379 | ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate), |
380 | ModuleDefId::ModuleId(id) => id.krate, | 380 | ItemInNs::Macros(id) => Some(id.krate), |
381 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, | 381 | } |
382 | ModuleDefId::AdtId(id) => id.module(db).krate, | ||
383 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate, | ||
384 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate, | ||
385 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate, | ||
386 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate, | ||
387 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | ||
388 | ModuleDefId::BuiltinType(_) => return None, | ||
389 | }, | ||
390 | ItemInNs::Macros(id) => return Some(id.krate), | ||
391 | }) | ||
392 | } | 382 | } |
393 | } | 383 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 6802bc250..4498d94bb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -97,6 +97,10 @@ impl ModuleId { | |||
97 | pub fn krate(&self) -> CrateId { | 97 | pub fn krate(&self) -> CrateId { |
98 | self.krate | 98 | self.krate |
99 | } | 99 | } |
100 | |||
101 | pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
102 | self.def_map(db).containing_module(self.local_id) | ||
103 | } | ||
100 | } | 104 | } |
101 | 105 | ||
102 | /// An ID of a module, **local** to a specific crate | 106 | /// An ID of a module, **local** to a specific crate |
@@ -529,6 +533,25 @@ impl HasModule for StaticLoc { | |||
529 | } | 533 | } |
530 | } | 534 | } |
531 | 535 | ||
536 | impl ModuleDefId { | ||
537 | /// Returns the module containing `self` (or `self`, if `self` is itself a module). | ||
538 | /// | ||
539 | /// Returns `None` if `self` refers to a primitive type. | ||
540 | pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
541 | Some(match self { | ||
542 | ModuleDefId::ModuleId(id) => *id, | ||
543 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), | ||
544 | ModuleDefId::AdtId(id) => id.module(db), | ||
545 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db), | ||
546 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), | ||
547 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db), | ||
548 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db), | ||
549 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), | ||
550 | ModuleDefId::BuiltinType(_) => return None, | ||
551 | }) | ||
552 | } | ||
553 | } | ||
554 | |||
532 | impl AttrDefId { | 555 | impl AttrDefId { |
533 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { | 556 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { |
534 | match self { | 557 | match self { |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 6a3456f2e..003d668ca 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -343,6 +343,18 @@ impl DefMap { | |||
343 | Some(self.block?.parent) | 343 | Some(self.block?.parent) |
344 | } | 344 | } |
345 | 345 | ||
346 | /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing | ||
347 | /// the block, if `self` corresponds to a block expression. | ||
348 | pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { | ||
349 | match &self[local_mod].parent { | ||
350 | Some(parent) => Some(self.module_id(*parent)), | ||
351 | None => match &self.block { | ||
352 | Some(block) => Some(block.parent), | ||
353 | None => None, | ||
354 | }, | ||
355 | } | ||
356 | } | ||
357 | |||
346 | // FIXME: this can use some more human-readable format (ideally, an IR | 358 | // FIXME: this can use some more human-readable format (ideally, an IR |
347 | // even), as this should be a great debugging aid. | 359 | // even), as this should be a great debugging aid. |
348 | pub fn dump(&self, db: &dyn DefDatabase) -> String { | 360 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index a469546c1..505493a74 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
101 | break; | 101 | break; |
102 | } | 102 | } |
103 | ast::PathSegmentKind::SelfKw => { | 103 | ast::PathSegmentKind::SelfKw => { |
104 | kind = PathKind::Super(0); | 104 | // don't break out if `self` is the last segment of a path, this mean we got an |
105 | break; | 105 | // use tree like `foo::{self}` which we want to resolve as `foo` |
106 | if !segments.is_empty() { | ||
107 | kind = PathKind::Super(0); | ||
108 | break; | ||
109 | } | ||
106 | } | 110 | } |
107 | ast::PathSegmentKind::SuperKw => { | 111 | ast::PathSegmentKind::SuperKw => { |
108 | let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; | 112 | let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; |
@@ -117,6 +121,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
117 | segments.reverse(); | 121 | segments.reverse(); |
118 | generic_args.reverse(); | 122 | generic_args.reverse(); |
119 | 123 | ||
124 | if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() { | ||
125 | // plain empty paths don't exist, this means we got a single `self` segment as our path | ||
126 | kind = PathKind::Super(0); | ||
127 | } | ||
128 | |||
120 | // handle local_inner_macros : | 129 | // handle local_inner_macros : |
121 | // Basically, even in rustc it is quite hacky: | 130 | // Basically, even in rustc it is quite hacky: |
122 | // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 | 131 | // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 6ef9d1e7e..d1302d749 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.58", default-features = false } | 20 | chalk-solve = { version = "0.59", default-features = false } |
21 | chalk-ir = "0.58" | 21 | chalk-ir = "0.59" |
22 | chalk-recursive = "0.58" | 22 | chalk-recursive = "0.59" |
23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
24 | 24 | ||
25 | stdx = { path = "../stdx", version = "0.0.0" } | 25 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 66a88e2b6..2751cd304 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -2,9 +2,7 @@ | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{expr::Statement, path::path, resolver::HasResolver, AssocItemId, DefWithBodyId}; |
6 | expr::Statement, path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, | ||
7 | }; | ||
8 | use hir_expand::{diagnostics::DiagnosticSink, name}; | 6 | use hir_expand::{diagnostics::DiagnosticSink, name}; |
9 | use rustc_hash::FxHashSet; | 7 | use rustc_hash::FxHashSet; |
10 | use syntax::{ast, AstPtr}; | 8 | use syntax::{ast, AstPtr}; |
@@ -17,7 +15,7 @@ use crate::{ | |||
17 | MissingPatFields, RemoveThisSemicolon, | 15 | MissingPatFields, RemoveThisSemicolon, |
18 | }, | 16 | }, |
19 | utils::variant_data, | 17 | utils::variant_data, |
20 | InferenceResult, Ty, | 18 | AdtId, InferenceResult, Ty, |
21 | }; | 19 | }; |
22 | 20 | ||
23 | pub(crate) use hir_def::{ | 21 | pub(crate) use hir_def::{ |
@@ -382,10 +380,14 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
382 | }; | 380 | }; |
383 | 381 | ||
384 | let (params, required) = match mismatch.expected { | 382 | let (params, required) = match mismatch.expected { |
385 | Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_result_enum => { | 383 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) |
384 | if enum_id == core_result_enum => | ||
385 | { | ||
386 | (parameters, "Ok".to_string()) | 386 | (parameters, "Ok".to_string()) |
387 | } | 387 | } |
388 | Ty::Adt(AdtId::EnumId(enum_id), ref parameters) if enum_id == core_option_enum => { | 388 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) |
389 | if enum_id == core_option_enum => | ||
390 | { | ||
389 | (parameters, "Some".to_string()) | 391 | (parameters, "Some".to_string()) |
390 | } | 392 | } |
391 | _ => return, | 393 | _ => return, |
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 86fee0050..04d39c571 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -222,12 +222,12 @@ use hir_def::{ | |||
222 | adt::VariantData, | 222 | adt::VariantData, |
223 | body::Body, | 223 | body::Body, |
224 | expr::{Expr, Literal, Pat, PatId}, | 224 | expr::{Expr, Literal, Pat, PatId}, |
225 | AdtId, EnumVariantId, StructId, VariantId, | 225 | EnumVariantId, StructId, VariantId, |
226 | }; | 226 | }; |
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, InferenceResult, Ty}; | 230 | use crate::{db::HirDatabase, AdtId, InferenceResult, Ty}; |
231 | 231 | ||
232 | #[derive(Debug, Clone, Copy)] | 232 | #[derive(Debug, Clone, Copy)] |
233 | /// Either a pattern from the source code being analyzed, represented as | 233 | /// Either a pattern from the source code being analyzed, represented as |
@@ -627,7 +627,7 @@ pub(super) fn is_useful( | |||
627 | // - `!` type | 627 | // - `!` type |
628 | // In those cases, no match arm is useful. | 628 | // In those cases, no match arm is useful. |
629 | match cx.infer[cx.match_expr].strip_references() { | 629 | match cx.infer[cx.match_expr].strip_references() { |
630 | Ty::Adt(AdtId::EnumId(enum_id), ..) => { | 630 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { |
631 | if cx.db.enum_data(*enum_id).variants.is_empty() { | 631 | if cx.db.enum_data(*enum_id).variants.is_empty() { |
632 | return Ok(Usefulness::NotUseful); | 632 | return Ok(Usefulness::NotUseful); |
633 | } | 633 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index f3a4333cb..a0882a2a1 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -2,18 +2,20 @@ | |||
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::{borrow::Cow, fmt}; |
4 | 4 | ||
5 | use crate::{ | ||
6 | db::HirDatabase, primitive, utils::generics, AliasTy, CallableDefId, CallableSig, | ||
7 | GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, | ||
8 | TraitRef, Ty, | ||
9 | }; | ||
10 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | ||
11 | use hir_def::{ | 7 | use hir_def::{ |
12 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, | 8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, |
13 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, | 9 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, |
14 | }; | 10 | }; |
15 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
16 | 12 | ||
13 | use crate::{ | ||
14 | db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, | ||
15 | GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, | ||
16 | TraitRef, Ty, | ||
17 | }; | ||
18 | |||
17 | pub struct HirFormatter<'a> { | 19 | pub struct HirFormatter<'a> { |
18 | pub db: &'a dyn HirDatabase, | 20 | pub db: &'a dyn HirDatabase, |
19 | fmt: &'a mut dyn fmt::Write, | 21 | fmt: &'a mut dyn fmt::Write, |
@@ -291,9 +293,23 @@ impl HirDisplay for Ty { | |||
291 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 293 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
292 | 294 | ||
293 | if matches!(self, Ty::Raw(..)) { | 295 | if matches!(self, Ty::Raw(..)) { |
294 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 296 | write!( |
297 | f, | ||
298 | "*{}", | ||
299 | match m { | ||
300 | Mutability::Not => "const ", | ||
301 | Mutability::Mut => "mut ", | ||
302 | } | ||
303 | )?; | ||
295 | } else { | 304 | } else { |
296 | write!(f, "&{}", m.as_keyword_for_ref())?; | 305 | write!( |
306 | f, | ||
307 | "&{}", | ||
308 | match m { | ||
309 | Mutability::Not => "", | ||
310 | Mutability::Mut => "mut ", | ||
311 | } | ||
312 | )?; | ||
297 | } | 313 | } |
298 | 314 | ||
299 | let datas; | 315 | let datas; |
@@ -385,13 +401,13 @@ impl HirDisplay for Ty { | |||
385 | write!(f, " -> {}", ret_display)?; | 401 | write!(f, " -> {}", ret_display)?; |
386 | } | 402 | } |
387 | } | 403 | } |
388 | Ty::Adt(def_id, parameters) => { | 404 | Ty::Adt(AdtId(def_id), parameters) => { |
389 | match f.display_target { | 405 | match f.display_target { |
390 | DisplayTarget::Diagnostics | DisplayTarget::Test => { | 406 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
391 | let name = match *def_id { | 407 | let name = match *def_id { |
392 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), | 408 | hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(), |
393 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), | 409 | hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(), |
394 | AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), | 410 | hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), |
395 | }; | 411 | }; |
396 | write!(f, "{}", name)?; | 412 | write!(f, "{}", name)?; |
397 | } | 413 | } |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 18a4f5e8a..4d771a91e 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,6 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | ||
21 | use hir_def::{ | 22 | use hir_def::{ |
22 | body::Body, | 23 | body::Body, |
23 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -25,7 +26,7 @@ use hir_def::{ | |||
25 | lang_item::LangItemTarget, | 26 | lang_item::LangItemTarget, |
26 | path::{path, Path}, | 27 | path::{path, Path}, |
27 | resolver::{HasResolver, Resolver, TypeNs}, | 28 | resolver::{HasResolver, Resolver, TypeNs}, |
28 | type_ref::{Mutability, TypeRef}, | 29 | type_ref::TypeRef, |
29 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, | 30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, |
30 | TypeAliasId, VariantId, | 31 | TypeAliasId, VariantId, |
31 | }; | 32 | }; |
@@ -87,7 +88,7 @@ impl BindingMode { | |||
87 | fn convert(annotation: BindingAnnotation) -> BindingMode { | 88 | fn convert(annotation: BindingAnnotation) -> BindingMode { |
88 | match annotation { | 89 | match annotation { |
89 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, | 90 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, |
90 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared), | 91 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not), |
91 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), | 92 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), |
92 | } | 93 | } |
93 | } | 94 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index c33d8c61e..cf0a3add4 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,8 +4,8 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use chalk_ir::TyVariableKind; | 7 | use chalk_ir::{Mutability, TyVariableKind}; |
8 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use test_utils::mark; | 9 | use test_utils::mark; |
10 | 10 | ||
11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; | 11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; |
@@ -73,20 +73,20 @@ impl<'a> InferenceContext<'a> { | |||
73 | match (&mut from_ty, to_ty) { | 73 | match (&mut from_ty, to_ty) { |
74 | // `*mut T` -> `*const T` | 74 | // `*mut T` -> `*const T` |
75 | // `&mut T` -> `&T` | 75 | // `&mut T` -> `&T` |
76 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Shared, ..)) | 76 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) |
77 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Shared, ..)) => { | 77 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { |
78 | *m1 = *m2; | 78 | *m1 = *m2; |
79 | } | 79 | } |
80 | // `&T` -> `*const T` | 80 | // `&T` -> `*const T` |
81 | // `&mut T` -> `*mut T`/`*const T` | 81 | // `&mut T` -> `*mut T`/`*const T` |
82 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Shared, ..)) | 82 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) |
83 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { | 83 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { |
84 | from_ty = Ty::Raw(m2, substs.clone()); | 84 | from_ty = Ty::Raw(m2, substs.clone()); |
85 | } | 85 | } |
86 | 86 | ||
87 | // Illegal mutability conversion | 87 | // Illegal mutability conversion |
88 | (Ty::Raw(Mutability::Shared, ..), Ty::Raw(Mutability::Mut, ..)) | 88 | (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) |
89 | | (Ty::Ref(Mutability::Shared, ..), Ty::Ref(Mutability::Mut, ..)) => return false, | 89 | | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, |
90 | 90 | ||
91 | // `{function_type}` -> `fn()` | 91 | // `{function_type}` -> `fn()` |
92 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { | 92 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 7852b3d23..ec2c13154 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,23 +3,25 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::TyVariableKind; | 6 | use chalk_ir::{Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use syntax::ast::RangeOp; | 14 | use syntax::ast::RangeOp; |
15 | use test_utils::mark; | 15 | use test_utils::mark; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, method_resolution, op, | 18 | autoderef, |
19 | lower::lower_to_chalk_mutability, | ||
20 | method_resolution, op, | ||
19 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
20 | traits::{FnTrait, InEnvironment}, | 22 | traits::{FnTrait, InEnvironment}, |
21 | utils::{generics, variant_data, Generics}, | 23 | utils::{generics, variant_data, Generics}, |
22 | Binders, CallableDefId, FnPointer, FnSig, Mutability, Obligation, OpaqueTyId, Rawness, Scalar, | 24 | AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, |
23 | Substs, TraitRef, Ty, | 25 | Substs, TraitRef, Ty, |
24 | }; | 26 | }; |
25 | 27 | ||
@@ -427,14 +429,14 @@ impl<'a> InferenceContext<'a> { | |||
427 | Ty::Tuple(_, substs) => { | 429 | Ty::Tuple(_, substs) => { |
428 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) | 430 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) |
429 | } | 431 | } |
430 | Ty::Adt(AdtId::StructId(s), parameters) => { | 432 | Ty::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
431 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { | 433 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { |
432 | let field = FieldId { parent: s.into(), local_id }; | 434 | let field = FieldId { parent: s.into(), local_id }; |
433 | self.write_field_resolution(tgt_expr, field); | 435 | self.write_field_resolution(tgt_expr, field); |
434 | self.db.field_types(s.into())[field.local_id].clone().subst(¶meters) | 436 | self.db.field_types(s.into())[field.local_id].clone().subst(¶meters) |
435 | }) | 437 | }) |
436 | } | 438 | } |
437 | Ty::Adt(AdtId::UnionId(u), parameters) => { | 439 | Ty::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { |
438 | self.db.union_data(u).variant_data.field(name).map(|local_id| { | 440 | self.db.union_data(u).variant_data.field(name).map(|local_id| { |
439 | let field = FieldId { parent: u.into(), local_id }; | 441 | let field = FieldId { parent: u.into(), local_id }; |
440 | self.write_field_resolution(tgt_expr, field); | 442 | self.write_field_resolution(tgt_expr, field); |
@@ -462,10 +464,11 @@ impl<'a> InferenceContext<'a> { | |||
462 | cast_ty | 464 | cast_ty |
463 | } | 465 | } |
464 | Expr::Ref { expr, rawness, mutability } => { | 466 | Expr::Ref { expr, rawness, mutability } => { |
467 | let mutability = lower_to_chalk_mutability(*mutability); | ||
465 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = | 468 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = |
466 | &expected.ty.as_reference_or_ptr() | 469 | &expected.ty.as_reference_or_ptr() |
467 | { | 470 | { |
468 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 471 | if *exp_mutability == Mutability::Mut && mutability == Mutability::Not { |
469 | // FIXME: throw type error - expected mut reference but found shared ref, | 472 | // FIXME: throw type error - expected mut reference but found shared ref, |
470 | // which cannot be coerced | 473 | // which cannot be coerced |
471 | } | 474 | } |
@@ -479,8 +482,8 @@ impl<'a> InferenceContext<'a> { | |||
479 | }; | 482 | }; |
480 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 483 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
481 | match rawness { | 484 | match rawness { |
482 | Rawness::RawPtr => Ty::Raw(*mutability, Substs::single(inner_ty)), | 485 | Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)), |
483 | Rawness::Ref => Ty::Ref(*mutability, Substs::single(inner_ty)), | 486 | Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), |
484 | } | 487 | } |
485 | } | 488 | } |
486 | Expr::Box { expr } => { | 489 | Expr::Box { expr } => { |
@@ -495,7 +498,7 @@ impl<'a> InferenceContext<'a> { | |||
495 | _ => (), | 498 | _ => (), |
496 | } | 499 | } |
497 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); | 500 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); |
498 | Ty::Adt(box_, sb.build()) | 501 | Ty::adt_ty(box_, sb.build()) |
499 | } else { | 502 | } else { |
500 | Ty::Unknown | 503 | Ty::Unknown |
501 | } | 504 | } |
@@ -583,31 +586,31 @@ impl<'a> InferenceContext<'a> { | |||
583 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 586 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
584 | match (range_type, lhs_ty, rhs_ty) { | 587 | match (range_type, lhs_ty, rhs_ty) { |
585 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 588 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
586 | Some(adt) => Ty::Adt(adt, Substs::empty()), | 589 | Some(adt) => Ty::adt_ty(adt, Substs::empty()), |
587 | None => Ty::Unknown, | 590 | None => Ty::Unknown, |
588 | }, | 591 | }, |
589 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 592 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
590 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), | 593 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
591 | None => Ty::Unknown, | 594 | None => Ty::Unknown, |
592 | }, | 595 | }, |
593 | (RangeOp::Inclusive, None, Some(ty)) => { | 596 | (RangeOp::Inclusive, None, Some(ty)) => { |
594 | match self.resolve_range_to_inclusive() { | 597 | match self.resolve_range_to_inclusive() { |
595 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), | 598 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
596 | None => Ty::Unknown, | 599 | None => Ty::Unknown, |
597 | } | 600 | } |
598 | } | 601 | } |
599 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { | 602 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { |
600 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), | 603 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
601 | None => Ty::Unknown, | 604 | None => Ty::Unknown, |
602 | }, | 605 | }, |
603 | (RangeOp::Inclusive, Some(_), Some(ty)) => { | 606 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
604 | match self.resolve_range_inclusive() { | 607 | match self.resolve_range_inclusive() { |
605 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), | 608 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
606 | None => Ty::Unknown, | 609 | None => Ty::Unknown, |
607 | } | 610 | } |
608 | } | 611 | } |
609 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { | 612 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { |
610 | Some(adt) => Ty::Adt(adt, Substs::single(ty)), | 613 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
611 | None => Ty::Unknown, | 614 | None => Ty::Unknown, |
612 | }, | 615 | }, |
613 | (RangeOp::Inclusive, _, None) => Ty::Unknown, | 616 | (RangeOp::Inclusive, _, None) => Ty::Unknown, |
@@ -684,11 +687,11 @@ impl<'a> InferenceContext<'a> { | |||
684 | } | 687 | } |
685 | Expr::Literal(lit) => match lit { | 688 | Expr::Literal(lit) => match lit { |
686 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), | 689 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), |
687 | Literal::String(..) => Ty::Ref(Mutability::Shared, Substs::single(Ty::Str)), | 690 | Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), |
688 | Literal::ByteString(..) => { | 691 | Literal::ByteString(..) => { |
689 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); | 692 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); |
690 | let array_type = Ty::Array(Substs::single(byte_type)); | 693 | let array_type = Ty::Array(Substs::single(byte_type)); |
691 | Ty::Ref(Mutability::Shared, Substs::single(array_type)) | 694 | Ty::Ref(Mutability::Not, Substs::single(array_type)) |
692 | } | 695 | } |
693 | Literal::Char(..) => Ty::Scalar(Scalar::Char), | 696 | Literal::Char(..) => Ty::Scalar(Scalar::Char), |
694 | Literal::Int(_v, ty) => match ty { | 697 | Literal::Int(_v, ty) => match ty { |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a318e47f3..987793e2e 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -3,17 +3,17 @@ | |||
3 | use std::iter::repeat; | 3 | use std::iter::repeat; |
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::Mutability; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, | 8 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 9 | path::Path, |
9 | type_ref::Mutability, | ||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty}; | 16 | use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; |
17 | 17 | ||
18 | impl<'a> InferenceContext<'a> { | 18 | impl<'a> InferenceContext<'a> { |
19 | fn infer_tuple_struct_pat( | 19 | fn infer_tuple_struct_pat( |
@@ -103,7 +103,7 @@ impl<'a> InferenceContext<'a> { | |||
103 | expected = inner; | 103 | expected = inner; |
104 | default_bm = match default_bm { | 104 | default_bm = match default_bm { |
105 | BindingMode::Move => BindingMode::Ref(mutability), | 105 | BindingMode::Move => BindingMode::Ref(mutability), |
106 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), | 106 | BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |
107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), | 107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), |
108 | } | 108 | } |
109 | } | 109 | } |
@@ -152,9 +152,10 @@ impl<'a> InferenceContext<'a> { | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | Pat::Ref { pat, mutability } => { | 154 | Pat::Ref { pat, mutability } => { |
155 | let mutability = lower_to_chalk_mutability(*mutability); | ||
155 | let expectation = match expected.as_reference() { | 156 | let expectation = match expected.as_reference() { |
156 | Some((inner_ty, exp_mut)) => { | 157 | Some((inner_ty, exp_mut)) => { |
157 | if *mutability != exp_mut { | 158 | if mutability != exp_mut { |
158 | // FIXME: emit type error? | 159 | // FIXME: emit type error? |
159 | } | 160 | } |
160 | inner_ty | 161 | inner_ty |
@@ -162,7 +163,7 @@ impl<'a> InferenceContext<'a> { | |||
162 | _ => &Ty::Unknown, | 163 | _ => &Ty::Unknown, |
163 | }; | 164 | }; |
164 | let subty = self.infer_pat(*pat, expectation, default_bm); | 165 | let subty = self.infer_pat(*pat, expectation, default_bm); |
165 | Ty::Ref(*mutability, Substs::single(subty)) | 166 | Ty::Ref(mutability, Substs::single(subty)) |
166 | } | 167 | } |
167 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 168 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
168 | p.as_ref(), | 169 | p.as_ref(), |
@@ -236,7 +237,7 @@ impl<'a> InferenceContext<'a> { | |||
236 | }; | 237 | }; |
237 | 238 | ||
238 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); | 239 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); |
239 | Ty::Adt(box_adt, Substs::single(inner_ty)) | 240 | Ty::adt_ty(box_adt, Substs::single(inner_ty)) |
240 | } | 241 | } |
241 | None => Ty::Unknown, | 242 | None => Ty::Unknown, |
242 | }, | 243 | }, |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 9bcaf6fa7..e77f24e4e 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -27,11 +27,9 @@ use std::{iter, mem, ops::Deref, sync::Arc}; | |||
27 | 27 | ||
28 | use base_db::salsa; | 28 | use base_db::salsa; |
29 | use hir_def::{ | 29 | use hir_def::{ |
30 | builtin_type::BuiltinType, | 30 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, DefWithBodyId, |
31 | expr::ExprId, | 31 | FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, |
32 | type_ref::{Mutability, Rawness}, | 32 | TypeParamId, |
33 | AdtId, AssocContainerId, DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId, | ||
34 | Lookup, TraitId, TypeAliasId, TypeParamId, | ||
35 | }; | 33 | }; |
36 | use itertools::Itertools; | 34 | use itertools::Itertools; |
37 | 35 | ||
@@ -49,7 +47,9 @@ pub use lower::{ | |||
49 | }; | 47 | }; |
50 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 48 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
51 | 49 | ||
52 | pub use chalk_ir::{BoundVar, DebruijnIndex, Scalar, TyVariableKind}; | 50 | pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; |
51 | |||
52 | pub(crate) use crate::traits::chalk::Interner; | ||
53 | 53 | ||
54 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 54 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
55 | pub enum Lifetime { | 55 | pub enum Lifetime { |
@@ -133,7 +133,7 @@ pub enum AliasTy { | |||
133 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 133 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
134 | pub enum Ty { | 134 | pub enum Ty { |
135 | /// Structures, enumerations and unions. | 135 | /// Structures, enumerations and unions. |
136 | Adt(AdtId, Substs), | 136 | Adt(AdtId<Interner>, Substs), |
137 | 137 | ||
138 | /// Represents an associated item like `Iterator::Item`. This is used | 138 | /// Represents an associated item like `Iterator::Item`. This is used |
139 | /// when we have tried to normalize a projection like `T::Item` but | 139 | /// when we have tried to normalize a projection like `T::Item` but |
@@ -604,6 +604,10 @@ impl Ty { | |||
604 | Ty::Tuple(0, Substs::empty()) | 604 | Ty::Tuple(0, Substs::empty()) |
605 | } | 605 | } |
606 | 606 | ||
607 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty { | ||
608 | Ty::Adt(AdtId(adt), substs) | ||
609 | } | ||
610 | |||
607 | pub fn fn_ptr(sig: CallableSig) -> Self { | 611 | pub fn fn_ptr(sig: CallableSig) -> Self { |
608 | Ty::Function(FnPointer { | 612 | Ty::Function(FnPointer { |
609 | num_args: sig.params().len(), | 613 | num_args: sig.params().len(), |
@@ -652,9 +656,9 @@ impl Ty { | |||
652 | t | 656 | t |
653 | } | 657 | } |
654 | 658 | ||
655 | pub fn as_adt(&self) -> Option<(AdtId, &Substs)> { | 659 | pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> { |
656 | match self { | 660 | match self { |
657 | Ty::Adt(adt_def, parameters) => Some((*adt_def, parameters)), | 661 | Ty::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), |
658 | _ => None, | 662 | _ => None, |
659 | } | 663 | } |
660 | } | 664 | } |
@@ -668,7 +672,7 @@ impl Ty { | |||
668 | 672 | ||
669 | pub fn as_generic_def(&self) -> Option<GenericDefId> { | 673 | pub fn as_generic_def(&self) -> Option<GenericDefId> { |
670 | match *self { | 674 | match *self { |
671 | Ty::Adt(adt, ..) => Some(adt.into()), | 675 | Ty::Adt(AdtId(adt), ..) => Some(adt.into()), |
672 | Ty::FnDef(callable, ..) => Some(callable.into()), | 676 | Ty::FnDef(callable, ..) => Some(callable.into()), |
673 | Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), | 677 | Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), |
674 | Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), | 678 | Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index ca06c9fe2..5fe5b8ad1 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -8,6 +8,7 @@ | |||
8 | use std::{iter, sync::Arc}; | 8 | use std::{iter, sync::Arc}; |
9 | 9 | ||
10 | use base_db::CrateId; | 10 | use base_db::CrateId; |
11 | use chalk_ir::Mutability; | ||
11 | use hir_def::{ | 12 | use hir_def::{ |
12 | adt::StructKind, | 13 | adt::StructKind, |
13 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
@@ -157,7 +158,7 @@ impl Ty { | |||
157 | } | 158 | } |
158 | TypeRef::RawPtr(inner, mutability) => { | 159 | TypeRef::RawPtr(inner, mutability) => { |
159 | let inner_ty = Ty::from_hir(ctx, inner); | 160 | let inner_ty = Ty::from_hir(ctx, inner); |
160 | Ty::Raw(*mutability, Substs::single(inner_ty)) | 161 | Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) |
161 | } | 162 | } |
162 | TypeRef::Array(inner) => { | 163 | TypeRef::Array(inner) => { |
163 | let inner_ty = Ty::from_hir(ctx, inner); | 164 | let inner_ty = Ty::from_hir(ctx, inner); |
@@ -169,7 +170,7 @@ impl Ty { | |||
169 | } | 170 | } |
170 | TypeRef::Reference(inner, _, mutability) => { | 171 | TypeRef::Reference(inner, _, mutability) => { |
171 | let inner_ty = Ty::from_hir(ctx, inner); | 172 | let inner_ty = Ty::from_hir(ctx, inner); |
172 | Ty::Ref(*mutability, Substs::single(inner_ty)) | 173 | Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) |
173 | } | 174 | } |
174 | TypeRef::Placeholder => Ty::Unknown, | 175 | TypeRef::Placeholder => Ty::Unknown, |
175 | TypeRef::Fn(params, is_varargs) => { | 176 | TypeRef::Fn(params, is_varargs) => { |
@@ -1099,7 +1100,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - | |||
1099 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { | 1100 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { |
1100 | let generics = generics(db.upcast(), adt.into()); | 1101 | let generics = generics(db.upcast(), adt.into()); |
1101 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1102 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
1102 | Binders::new(substs.len(), Ty::Adt(adt, substs)) | 1103 | Binders::new(substs.len(), Ty::adt_ty(adt, substs)) |
1103 | } | 1104 | } |
1104 | 1105 | ||
1105 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | 1106 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
@@ -1259,3 +1260,10 @@ pub(crate) fn return_type_impl_traits( | |||
1259 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) | 1260 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) |
1260 | } | 1261 | } |
1261 | } | 1262 | } |
1263 | |||
1264 | pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability { | ||
1265 | match m { | ||
1266 | hir_def::type_ref::Mutability::Shared => Mutability::Not, | ||
1267 | hir_def::type_ref::Mutability::Mut => Mutability::Mut, | ||
1268 | } | ||
1269 | } | ||
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index dd5109d4e..dfcf346fb 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,9 +6,10 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | ||
9 | use hir_def::{ | 10 | use hir_def::{ |
10 | lang_item::LangItemTarget, type_ref::Mutability, AdtId, AssocContainerId, AssocItemId, | 11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, |
11 | FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId, | 12 | ImplId, Lookup, ModuleId, TraitId, TypeAliasId, |
12 | }; | 13 | }; |
13 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
14 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -18,8 +19,8 @@ use crate::{ | |||
18 | db::HirDatabase, | 19 | db::HirDatabase, |
19 | primitive::{self, FloatTy, IntTy, UintTy}, | 20 | primitive::{self, FloatTy, IntTy, UintTy}, |
20 | utils::all_super_traits, | 21 | utils::all_super_traits, |
21 | Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, TraitEnvironment, | 22 | AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, |
22 | TraitRef, Ty, TypeWalk, | 23 | TraitEnvironment, TraitRef, Ty, TypeWalk, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | /// This is used as a key for indexing impls. | 26 | /// This is used as a key for indexing impls. |
@@ -31,7 +32,7 @@ pub enum TyFingerprint { | |||
31 | Never, | 32 | Never, |
32 | RawPtr(Mutability), | 33 | RawPtr(Mutability), |
33 | Scalar(Scalar), | 34 | Scalar(Scalar), |
34 | Adt(AdtId), | 35 | Adt(hir_def::AdtId), |
35 | Dyn(TraitId), | 36 | Dyn(TraitId), |
36 | Tuple(usize), | 37 | Tuple(usize), |
37 | ForeignType(TypeAliasId), | 38 | ForeignType(TypeAliasId), |
@@ -49,7 +50,7 @@ impl TyFingerprint { | |||
49 | &Ty::Slice(..) => TyFingerprint::Slice, | 50 | &Ty::Slice(..) => TyFingerprint::Slice, |
50 | &Ty::Array(..) => TyFingerprint::Array, | 51 | &Ty::Array(..) => TyFingerprint::Array, |
51 | &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), | 52 | &Ty::Scalar(scalar) => TyFingerprint::Scalar(scalar), |
52 | &Ty::Adt(adt, _) => TyFingerprint::Adt(adt), | 53 | &Ty::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), |
53 | &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), | 54 | &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), |
54 | &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), | 55 | &Ty::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), |
55 | &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), | 56 | &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), |
@@ -230,7 +231,7 @@ impl Ty { | |||
230 | let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); | 231 | let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); |
231 | 232 | ||
232 | let lang_item_targets = match self { | 233 | let lang_item_targets = match self { |
233 | Ty::Adt(def_id, _) => { | 234 | Ty::Adt(AdtId(def_id), _) => { |
234 | return mod_to_crate_ids(def_id.module(db.upcast())); | 235 | return mod_to_crate_ids(def_id.module(db.upcast())); |
235 | } | 236 | } |
236 | Ty::ForeignType(type_alias_id) => { | 237 | Ty::ForeignType(type_alias_id) => { |
@@ -251,7 +252,7 @@ impl Ty { | |||
251 | } | 252 | } |
252 | Ty::Str => lang_item_crate!("str_alloc", "str"), | 253 | Ty::Str => lang_item_crate!("str_alloc", "str"), |
253 | Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), | 254 | Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), |
254 | Ty::Raw(Mutability::Shared, _) => lang_item_crate!("const_ptr"), | 255 | Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), |
255 | Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), | 256 | Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), |
256 | Ty::Dyn(_) => { | 257 | Ty::Dyn(_) => { |
257 | return self.dyn_trait().and_then(|trait_| { | 258 | return self.dyn_trait().and_then(|trait_| { |
@@ -429,7 +430,7 @@ fn iterate_method_candidates_with_autoref( | |||
429 | } | 430 | } |
430 | let refed = Canonical { | 431 | let refed = Canonical { |
431 | kinds: deref_chain[0].kinds.clone(), | 432 | kinds: deref_chain[0].kinds.clone(), |
432 | value: Ty::Ref(Mutability::Shared, Substs::single(deref_chain[0].value.clone())), | 433 | value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())), |
433 | }; | 434 | }; |
434 | if iterate_method_candidates_by_receiver( | 435 | if iterate_method_candidates_by_receiver( |
435 | &refed, | 436 | &refed, |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index e513fa8f4..4378a9723 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -315,9 +315,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
315 | let id = from_chalk(self.db, trait_id); | 315 | let id = from_chalk(self.db, trait_id); |
316 | self.db.trait_data(id).name.to_string() | 316 | self.db.trait_data(id).name.to_string() |
317 | } | 317 | } |
318 | fn adt_name(&self, adt_id: chalk_ir::AdtId<Interner>) -> String { | 318 | fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { |
319 | let id = from_chalk(self.db, adt_id); | 319 | match adt_id { |
320 | match id { | ||
321 | hir_def::AdtId::StructId(id) => self.db.struct_data(id).name.to_string(), | 320 | hir_def::AdtId::StructId(id) => self.db.struct_data(id).name.to_string(), |
322 | hir_def::AdtId::EnumId(id) => self.db.enum_data(id).name.to_string(), | 321 | hir_def::AdtId::EnumId(id) => self.db.enum_data(id).name.to_string(), |
323 | hir_def::AdtId::UnionId(id) => self.db.union_data(id).name.to_string(), | 322 | hir_def::AdtId::UnionId(id) => self.db.union_data(id).name.to_string(), |
@@ -488,8 +487,8 @@ pub(crate) fn struct_datum_query( | |||
488 | struct_id: AdtId, | 487 | struct_id: AdtId, |
489 | ) -> Arc<StructDatum> { | 488 | ) -> Arc<StructDatum> { |
490 | debug!("struct_datum {:?}", struct_id); | 489 | debug!("struct_datum {:?}", struct_id); |
491 | let adt_id = from_chalk(db, struct_id); | 490 | let type_ctor = Ty::Adt(struct_id, Substs::empty()); |
492 | let type_ctor = Ty::Adt(adt_id, Substs::empty()); | 491 | let chalk_ir::AdtId(adt_id) = struct_id; |
493 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 492 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
494 | let num_params = generics(db.upcast(), adt_id.into()).len(); | 493 | let num_params = generics(db.upcast(), adt_id.into()).len(); |
495 | let upstream = adt_id.module(db.upcast()).krate() != krate; | 494 | let upstream = adt_id.module(db.upcast()).krate() != krate; |
@@ -684,10 +683,9 @@ pub(crate) fn fn_def_variance_query( | |||
684 | pub(crate) fn adt_variance_query( | 683 | pub(crate) fn adt_variance_query( |
685 | db: &dyn HirDatabase, | 684 | db: &dyn HirDatabase, |
686 | _krate: CrateId, | 685 | _krate: CrateId, |
687 | adt_id: AdtId, | 686 | chalk_ir::AdtId(adt_id): AdtId, |
688 | ) -> Variances { | 687 | ) -> Variances { |
689 | let adt: crate::AdtId = from_chalk(db, adt_id); | 688 | let generic_params = generics(db.upcast(), adt_id.into()); |
690 | let generic_params = generics(db.upcast(), adt.into()); | ||
691 | Variances::from_iter( | 689 | Variances::from_iter( |
692 | &Interner, | 690 | &Interner, |
693 | std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), | 691 | std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 6e6055d80..3a08b67e9 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -10,7 +10,7 @@ use chalk_ir::{ | |||
10 | use chalk_solve::rust_ir; | 10 | use chalk_solve::rust_ir; |
11 | 11 | ||
12 | use base_db::salsa::InternKey; | 12 | use base_db::salsa::InternKey; |
13 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 13 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | db::HirDatabase, | 16 | db::HirDatabase, |
@@ -65,7 +65,7 @@ impl ToChalk for Ty { | |||
65 | } | 65 | } |
66 | Ty::Raw(mutability, substs) => { | 66 | Ty::Raw(mutability, substs) => { |
67 | let ty = substs[0].clone().to_chalk(db); | 67 | let ty = substs[0].clone().to_chalk(db); |
68 | chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner) | 68 | chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) |
69 | } | 69 | } |
70 | Ty::Slice(substs) => { | 70 | Ty::Slice(substs) => { |
71 | chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) | 71 | chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) |
@@ -86,7 +86,7 @@ impl ToChalk for Ty { | |||
86 | 86 | ||
87 | Ty::Adt(adt_id, substs) => { | 87 | Ty::Adt(adt_id, substs) => { |
88 | let substitution = substs.to_chalk(db); | 88 | let substitution = substs.to_chalk(db); |
89 | chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner) | 89 | chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) |
90 | } | 90 | } |
91 | Ty::Alias(AliasTy::Projection(proj_ty)) => { | 91 | Ty::Alias(AliasTy::Projection(proj_ty)) => { |
92 | let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); | 92 | let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); |
@@ -183,7 +183,7 @@ impl ToChalk for Ty { | |||
183 | Ty::Dyn(predicates) | 183 | Ty::Dyn(predicates) |
184 | } | 184 | } |
185 | 185 | ||
186 | chalk_ir::TyKind::Adt(struct_id, subst) => Ty::Adt(struct_id.0, from_chalk(db, subst)), | 186 | chalk_ir::TyKind::Adt(adt_id, subst) => Ty::Adt(adt_id, from_chalk(db, subst)), |
187 | chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType( | 187 | chalk_ir::TyKind::AssociatedType(type_id, subst) => Ty::AssociatedType( |
188 | from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0, | 188 | from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0, |
189 | from_chalk(db, subst), | 189 | from_chalk(db, subst), |
@@ -198,11 +198,11 @@ impl ToChalk for Ty { | |||
198 | Ty::Tuple(cardinality, from_chalk(db, subst)) | 198 | Ty::Tuple(cardinality, from_chalk(db, subst)) |
199 | } | 199 | } |
200 | chalk_ir::TyKind::Raw(mutability, ty) => { | 200 | chalk_ir::TyKind::Raw(mutability, ty) => { |
201 | Ty::Raw(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) | 201 | Ty::Raw(mutability, Substs::single(from_chalk(db, ty))) |
202 | } | 202 | } |
203 | chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), | 203 | chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), |
204 | chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { | 204 | chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { |
205 | Ty::Ref(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) | 205 | Ty::Ref(mutability, Substs::single(from_chalk(db, ty))) |
206 | } | 206 | } |
207 | chalk_ir::TyKind::Str => Ty::Str, | 207 | chalk_ir::TyKind::Str => Ty::Str, |
208 | chalk_ir::TyKind::Never => Ty::Never, | 208 | chalk_ir::TyKind::Never => Ty::Never, |
@@ -230,12 +230,12 @@ impl ToChalk for Ty { | |||
230 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | 230 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. |
231 | fn ref_to_chalk( | 231 | fn ref_to_chalk( |
232 | db: &dyn HirDatabase, | 232 | db: &dyn HirDatabase, |
233 | mutability: Mutability, | 233 | mutability: chalk_ir::Mutability, |
234 | subst: Substs, | 234 | subst: Substs, |
235 | ) -> chalk_ir::Ty<Interner> { | 235 | ) -> chalk_ir::Ty<Interner> { |
236 | let arg = subst[0].clone().to_chalk(db); | 236 | let arg = subst[0].clone().to_chalk(db); |
237 | let lifetime = LifetimeData::Static.intern(&Interner); | 237 | let lifetime = LifetimeData::Static.intern(&Interner); |
238 | chalk_ir::TyKind::Ref(mutability.to_chalk(db), lifetime, arg).intern(&Interner) | 238 | chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner) |
239 | } | 239 | } |
240 | 240 | ||
241 | /// We currently don't model constants, but Chalk does. So, we have to insert a | 241 | /// We currently don't model constants, but Chalk does. So, we have to insert a |
@@ -313,22 +313,6 @@ impl ToChalk for OpaqueTyId { | |||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | impl ToChalk for Mutability { | ||
317 | type Chalk = chalk_ir::Mutability; | ||
318 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
319 | match self { | ||
320 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
321 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
322 | } | ||
323 | } | ||
324 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
325 | match chalk { | ||
326 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
327 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | impl ToChalk for hir_def::ImplId { | 316 | impl ToChalk for hir_def::ImplId { |
333 | type Chalk = ImplId; | 317 | type Chalk = ImplId; |
334 | 318 | ||
@@ -341,18 +325,6 @@ impl ToChalk for hir_def::ImplId { | |||
341 | } | 325 | } |
342 | } | 326 | } |
343 | 327 | ||
344 | impl ToChalk for hir_def::AdtId { | ||
345 | type Chalk = AdtId; | ||
346 | |||
347 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
348 | chalk_ir::AdtId(self.into()) | ||
349 | } | ||
350 | |||
351 | fn from_chalk(_db: &dyn HirDatabase, id: AdtId) -> Self { | ||
352 | id.0 | ||
353 | } | ||
354 | } | ||
355 | |||
356 | impl ToChalk for CallableDefId { | 328 | impl ToChalk for CallableDefId { |
357 | type Chalk = FnDefId; | 329 | type Chalk = FnDefId; |
358 | 330 | ||
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs index 45170dd29..4b1b24562 100644 --- a/crates/ide/src/folding_ranges.rs +++ b/crates/ide/src/folding_ranges.rs | |||
@@ -6,7 +6,7 @@ use syntax::{ | |||
6 | ast::{self, AstNode, AstToken, VisibilityOwner}, | 6 | ast::{self, AstNode, AstToken, VisibilityOwner}, |
7 | Direction, NodeOrToken, SourceFile, | 7 | Direction, NodeOrToken, SourceFile, |
8 | SyntaxKind::{self, *}, | 8 | SyntaxKind::{self, *}, |
9 | SyntaxNode, TextRange, | 9 | SyntaxNode, TextRange, TextSize, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | #[derive(Debug, PartialEq, Eq)] | 12 | #[derive(Debug, PartialEq, Eq)] |
@@ -16,6 +16,7 @@ pub enum FoldKind { | |||
16 | Mods, | 16 | Mods, |
17 | Block, | 17 | Block, |
18 | ArgList, | 18 | ArgList, |
19 | Region, | ||
19 | } | 20 | } |
20 | 21 | ||
21 | #[derive(Debug)] | 22 | #[derive(Debug)] |
@@ -29,6 +30,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
29 | let mut visited_comments = FxHashSet::default(); | 30 | let mut visited_comments = FxHashSet::default(); |
30 | let mut visited_imports = FxHashSet::default(); | 31 | let mut visited_imports = FxHashSet::default(); |
31 | let mut visited_mods = FxHashSet::default(); | 32 | let mut visited_mods = FxHashSet::default(); |
33 | // regions can be nested, here is a LIFO buffer | ||
34 | let mut regions_starts: Vec<TextSize> = vec![]; | ||
32 | 35 | ||
33 | for element in file.syntax().descendants_with_tokens() { | 36 | for element in file.syntax().descendants_with_tokens() { |
34 | // Fold items that span multiple lines | 37 | // Fold items that span multiple lines |
@@ -48,10 +51,25 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
48 | // Fold groups of comments | 51 | // Fold groups of comments |
49 | if let Some(comment) = ast::Comment::cast(token) { | 52 | if let Some(comment) = ast::Comment::cast(token) { |
50 | if !visited_comments.contains(&comment) { | 53 | if !visited_comments.contains(&comment) { |
51 | if let Some(range) = | 54 | // regions are not real comments |
52 | contiguous_range_for_comment(comment, &mut visited_comments) | 55 | if comment.text().trim().starts_with("// region:") { |
53 | { | 56 | regions_starts.push(comment.syntax().text_range().start()); |
54 | res.push(Fold { range, kind: FoldKind::Comment }) | 57 | } else if comment.text().trim().starts_with("// endregion") { |
58 | if let Some(region) = regions_starts.pop() { | ||
59 | res.push(Fold { | ||
60 | range: TextRange::new( | ||
61 | region, | ||
62 | comment.syntax().text_range().end(), | ||
63 | ), | ||
64 | kind: FoldKind::Region, | ||
65 | }) | ||
66 | } | ||
67 | } else { | ||
68 | if let Some(range) = | ||
69 | contiguous_range_for_comment(comment, &mut visited_comments) | ||
70 | { | ||
71 | res.push(Fold { range, kind: FoldKind::Comment }) | ||
72 | } | ||
55 | } | 73 | } |
56 | } | 74 | } |
57 | } | 75 | } |
@@ -175,9 +193,16 @@ fn contiguous_range_for_comment( | |||
175 | } | 193 | } |
176 | if let Some(c) = ast::Comment::cast(token) { | 194 | if let Some(c) = ast::Comment::cast(token) { |
177 | if c.kind() == group_kind { | 195 | if c.kind() == group_kind { |
178 | visited.insert(c.clone()); | 196 | // regions are not real comments |
179 | last = c; | 197 | if c.text().trim().starts_with("// region:") |
180 | continue; | 198 | || c.text().trim().starts_with("// endregion") |
199 | { | ||
200 | break; | ||
201 | } else { | ||
202 | visited.insert(c.clone()); | ||
203 | last = c; | ||
204 | continue; | ||
205 | } | ||
181 | } | 206 | } |
182 | } | 207 | } |
183 | // The comment group ends because either: | 208 | // The comment group ends because either: |
@@ -224,6 +249,7 @@ mod tests { | |||
224 | FoldKind::Mods => "mods", | 249 | FoldKind::Mods => "mods", |
225 | FoldKind::Block => "block", | 250 | FoldKind::Block => "block", |
226 | FoldKind::ArgList => "arglist", | 251 | FoldKind::ArgList => "arglist", |
252 | FoldKind::Region => "region", | ||
227 | }; | 253 | }; |
228 | assert_eq!(kind, &attr.unwrap()); | 254 | assert_eq!(kind, &attr.unwrap()); |
229 | } | 255 | } |
@@ -418,4 +444,17 @@ fn foo<fold arglist>( | |||
418 | "#, | 444 | "#, |
419 | ) | 445 | ) |
420 | } | 446 | } |
447 | |||
448 | #[test] | ||
449 | fn fold_region() { | ||
450 | check( | ||
451 | r#" | ||
452 | // 1. some normal comment | ||
453 | <fold region>// region: test | ||
454 | // 2. some normal comment | ||
455 | calling_function(x,y); | ||
456 | // endregion: test</fold> | ||
457 | "#, | ||
458 | ) | ||
459 | } | ||
421 | } | 460 | } |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 9a605b09d..a9454cfa3 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -5,6 +5,7 @@ use hir::{ | |||
5 | use ide_db::{ | 5 | use ide_db::{ |
6 | base_db::SourceDatabase, | 6 | base_db::SourceDatabase, |
7 | defs::{Definition, NameClass, NameRefClass}, | 7 | defs::{Definition, NameClass, NameRefClass}, |
8 | helpers::FamousDefs, | ||
8 | RootDatabase, | 9 | RootDatabase, |
9 | }; | 10 | }; |
10 | use itertools::Itertools; | 11 | use itertools::Itertools; |
@@ -107,16 +108,14 @@ pub(crate) fn hover( | |||
107 | } | 108 | } |
108 | }; | 109 | }; |
109 | if let Some(definition) = definition { | 110 | if let Some(definition) = definition { |
110 | if let Some(markup) = hover_for_definition(db, definition) { | 111 | let famous_defs = match &definition { |
111 | let markup = markup.as_str(); | 112 | Definition::ModuleDef(ModuleDef::BuiltinType(_)) => { |
112 | let markup = if !markdown { | 113 | Some(FamousDefs(&sema, sema.scope(&node).krate())) |
113 | remove_markdown(markup) | 114 | } |
114 | } else if links_in_hover { | 115 | _ => None, |
115 | rewrite_links(db, markup, &definition) | 116 | }; |
116 | } else { | 117 | if let Some(markup) = hover_for_definition(db, definition, famous_defs.as_ref()) { |
117 | remove_links(markup) | 118 | res.markup = process_markup(sema.db, definition, &markup, links_in_hover, markdown); |
118 | }; | ||
119 | res.markup = Markup::from(markup); | ||
120 | if let Some(action) = show_implementations_action(db, definition) { | 119 | if let Some(action) = show_implementations_action(db, definition) { |
121 | res.actions.push(action); | 120 | res.actions.push(action); |
122 | } | 121 | } |
@@ -138,6 +137,9 @@ pub(crate) fn hover( | |||
138 | // don't highlight the entire parent node on comment hover | 137 | // don't highlight the entire parent node on comment hover |
139 | return None; | 138 | return None; |
140 | } | 139 | } |
140 | if let res @ Some(_) = hover_for_keyword(&sema, links_in_hover, markdown, &token) { | ||
141 | return res; | ||
142 | } | ||
141 | 143 | ||
142 | let node = token | 144 | let node = token |
143 | .ancestors() | 145 | .ancestors() |
@@ -272,6 +274,24 @@ fn hover_markup( | |||
272 | } | 274 | } |
273 | } | 275 | } |
274 | 276 | ||
277 | fn process_markup( | ||
278 | db: &RootDatabase, | ||
279 | def: Definition, | ||
280 | markup: &Markup, | ||
281 | links_in_hover: bool, | ||
282 | markdown: bool, | ||
283 | ) -> Markup { | ||
284 | let markup = markup.as_str(); | ||
285 | let markup = if !markdown { | ||
286 | remove_markdown(markup) | ||
287 | } else if links_in_hover { | ||
288 | rewrite_links(db, markup, &def) | ||
289 | } else { | ||
290 | remove_links(markup) | ||
291 | }; | ||
292 | Markup::from(markup) | ||
293 | } | ||
294 | |||
275 | fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> { | 295 | fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> { |
276 | match def { | 296 | match def { |
277 | Definition::Field(f) => Some(f.parent_def(db).name(db)), | 297 | Definition::Field(f) => Some(f.parent_def(db).name(db)), |
@@ -304,7 +324,11 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | |||
304 | def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def))) | 324 | def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def))) |
305 | } | 325 | } |
306 | 326 | ||
307 | fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | 327 | fn hover_for_definition( |
328 | db: &RootDatabase, | ||
329 | def: Definition, | ||
330 | famous_defs: Option<&FamousDefs>, | ||
331 | ) -> Option<Markup> { | ||
308 | let mod_path = definition_mod_path(db, &def); | 332 | let mod_path = definition_mod_path(db, &def); |
309 | return match def { | 333 | return match def { |
310 | Definition::Macro(it) => { | 334 | Definition::Macro(it) => { |
@@ -339,7 +363,9 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
339 | ModuleDef::Static(it) => from_def_source(db, it, mod_path), | 363 | ModuleDef::Static(it) => from_def_source(db, it, mod_path), |
340 | ModuleDef::Trait(it) => from_def_source(db, it, mod_path), | 364 | ModuleDef::Trait(it) => from_def_source(db, it, mod_path), |
341 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), | 365 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), |
342 | ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it.name())), | 366 | ModuleDef::BuiltinType(it) => famous_defs |
367 | .and_then(|fd| hover_for_builtin(fd, it)) | ||
368 | .or_else(|| Some(Markup::fenced_block(&it.name()))), | ||
343 | }, | 369 | }, |
344 | Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))), | 370 | Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))), |
345 | Definition::SelfType(impl_def) => { | 371 | Definition::SelfType(impl_def) => { |
@@ -380,11 +406,52 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
380 | } | 406 | } |
381 | } | 407 | } |
382 | 408 | ||
409 | fn hover_for_keyword( | ||
410 | sema: &Semantics<RootDatabase>, | ||
411 | links_in_hover: bool, | ||
412 | markdown: bool, | ||
413 | token: &SyntaxToken, | ||
414 | ) -> Option<RangeInfo<HoverResult>> { | ||
415 | if !token.kind().is_keyword() { | ||
416 | return None; | ||
417 | } | ||
418 | let famous_defs = FamousDefs(&sema, sema.scope(&token.parent()).krate()); | ||
419 | // std exposes {}_keyword modules with docstrings on the root to document keywords | ||
420 | let keyword_mod = format!("{}_keyword", token.text()); | ||
421 | let doc_owner = find_std_module(&famous_defs, &keyword_mod)?; | ||
422 | let docs = doc_owner.attrs(sema.db).docs()?; | ||
423 | let markup = process_markup( | ||
424 | sema.db, | ||
425 | Definition::ModuleDef(doc_owner.into()), | ||
426 | &hover_markup(Some(docs.into()), Some(token.text().into()), None)?, | ||
427 | links_in_hover, | ||
428 | markdown, | ||
429 | ); | ||
430 | Some(RangeInfo::new(token.text_range(), HoverResult { markup, actions: Default::default() })) | ||
431 | } | ||
432 | |||
433 | fn hover_for_builtin(famous_defs: &FamousDefs, builtin: hir::BuiltinType) -> Option<Markup> { | ||
434 | // std exposes prim_{} modules with docstrings on the root to document the builtins | ||
435 | let primitive_mod = format!("prim_{}", builtin.name()); | ||
436 | let doc_owner = find_std_module(famous_defs, &primitive_mod)?; | ||
437 | let docs = doc_owner.attrs(famous_defs.0.db).docs()?; | ||
438 | hover_markup(Some(docs.into()), Some(builtin.name().to_string()), None) | ||
439 | } | ||
440 | |||
441 | fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> { | ||
442 | let db = famous_defs.0.db; | ||
443 | let std_crate = famous_defs.std()?; | ||
444 | let std_root_module = std_crate.root_module(db); | ||
445 | std_root_module | ||
446 | .children(db) | ||
447 | .find(|module| module.name(db).map_or(false, |module| module.to_string() == name)) | ||
448 | } | ||
449 | |||
383 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | 450 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { |
384 | return tokens.max_by_key(priority); | 451 | return tokens.max_by_key(priority); |
385 | fn priority(n: &SyntaxToken) -> usize { | 452 | fn priority(n: &SyntaxToken) -> usize { |
386 | match n.kind() { | 453 | match n.kind() { |
387 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] => 3, | 454 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3, |
388 | T!['('] | T![')'] => 2, | 455 | T!['('] | T![')'] => 2, |
389 | kind if kind.is_trivia() => 0, | 456 | kind if kind.is_trivia() => 0, |
390 | _ => 1, | 457 | _ => 1, |
@@ -3496,4 +3563,75 @@ mod foo$0; | |||
3496 | "#]], | 3563 | "#]], |
3497 | ); | 3564 | ); |
3498 | } | 3565 | } |
3566 | |||
3567 | #[test] | ||
3568 | fn hover_self_in_use() { | ||
3569 | check( | ||
3570 | r#" | ||
3571 | //! This should not appear | ||
3572 | mod foo { | ||
3573 | /// But this should appear | ||
3574 | pub mod bar {} | ||
3575 | } | ||
3576 | use foo::bar::{self$0}; | ||
3577 | "#, | ||
3578 | expect![[r#" | ||
3579 | *self* | ||
3580 | |||
3581 | ```rust | ||
3582 | test::foo | ||
3583 | ``` | ||
3584 | |||
3585 | ```rust | ||
3586 | pub mod bar | ||
3587 | ``` | ||
3588 | |||
3589 | --- | ||
3590 | |||
3591 | But this should appear | ||
3592 | "#]], | ||
3593 | ) | ||
3594 | } | ||
3595 | |||
3596 | #[test] | ||
3597 | fn hover_keyword() { | ||
3598 | let ra_fixture = r#"//- /main.rs crate:main deps:std | ||
3599 | fn f() { retur$0n; }"#; | ||
3600 | let fixture = format!("{}\n{}", ra_fixture, FamousDefs::FIXTURE); | ||
3601 | check( | ||
3602 | &fixture, | ||
3603 | expect![[r#" | ||
3604 | *return* | ||
3605 | |||
3606 | ```rust | ||
3607 | return | ||
3608 | ``` | ||
3609 | |||
3610 | --- | ||
3611 | |||
3612 | Docs for return_keyword | ||
3613 | "#]], | ||
3614 | ); | ||
3615 | } | ||
3616 | |||
3617 | #[test] | ||
3618 | fn hover_builtin() { | ||
3619 | let ra_fixture = r#"//- /main.rs crate:main deps:std | ||
3620 | cosnt _: &str$0 = ""; }"#; | ||
3621 | let fixture = format!("{}\n{}", ra_fixture, FamousDefs::FIXTURE); | ||
3622 | check( | ||
3623 | &fixture, | ||
3624 | expect![[r#" | ||
3625 | *str* | ||
3626 | |||
3627 | ```rust | ||
3628 | str | ||
3629 | ``` | ||
3630 | |||
3631 | --- | ||
3632 | |||
3633 | Docs for prim_str | ||
3634 | "#]], | ||
3635 | ); | ||
3636 | } | ||
3499 | } | 3637 | } |
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 2c077ed1f..7fcae13e0 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -7,6 +7,7 @@ use syntax::{ | |||
7 | SyntaxKind::{self, USE_TREE, WHITESPACE}, | 7 | SyntaxKind::{self, USE_TREE, WHITESPACE}, |
8 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, | 8 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, |
9 | }; | 9 | }; |
10 | use test_utils::mark; | ||
10 | use text_edit::{TextEdit, TextEditBuilder}; | 11 | use text_edit::{TextEdit, TextEditBuilder}; |
11 | 12 | ||
12 | // Feature: Join Lines | 13 | // Feature: Join Lines |
@@ -44,9 +45,9 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit { | |||
44 | let text = token.text(); | 45 | let text = token.text(); |
45 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { | 46 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { |
46 | let pos: TextSize = (pos as u32).into(); | 47 | let pos: TextSize = (pos as u32).into(); |
47 | let off = token.text_range().start() + range.start() + pos; | 48 | let offset = token.text_range().start() + range.start() + pos; |
48 | if !edit.invalidates_offset(off) { | 49 | if !edit.invalidates_offset(offset) { |
49 | remove_newline(&mut edit, &token, off); | 50 | remove_newline(&mut edit, &token, offset); |
50 | } | 51 | } |
51 | } | 52 | } |
52 | } | 53 | } |
@@ -56,14 +57,25 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit { | |||
56 | 57 | ||
57 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { | 58 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { |
58 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { | 59 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { |
59 | // The node is either the first or the last in the file | 60 | let mut string_open_quote = false; |
60 | let suff = &token.text()[TextRange::new( | 61 | if let Some(string) = ast::String::cast(token.clone()) { |
61 | offset - token.text_range().start() + TextSize::of('\n'), | 62 | if let Some(range) = string.open_quote_text_range() { |
62 | TextSize::of(token.text()), | 63 | mark::hit!(join_string_literal); |
63 | )]; | 64 | string_open_quote = range.end() == offset; |
64 | let spaces = suff.bytes().take_while(|&b| b == b' ').count(); | 65 | } |
65 | 66 | } | |
66 | edit.replace(TextRange::at(offset, ((spaces + 1) as u32).into()), " ".to_string()); | 67 | |
68 | let n_spaces_after_line_break = { | ||
69 | let suff = &token.text()[TextRange::new( | ||
70 | offset - token.text_range().start() + TextSize::of('\n'), | ||
71 | TextSize::of(token.text()), | ||
72 | )]; | ||
73 | suff.bytes().take_while(|&b| b == b' ').count() | ||
74 | }; | ||
75 | |||
76 | let range = TextRange::at(offset, ((n_spaces_after_line_break + 1) as u32).into()); | ||
77 | let replace_with = if string_open_quote { "" } else { " " }; | ||
78 | edit.replace(range, replace_with.to_string()); | ||
67 | return; | 79 | return; |
68 | } | 80 | } |
69 | 81 | ||
@@ -194,7 +206,7 @@ fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str { | |||
194 | #[cfg(test)] | 206 | #[cfg(test)] |
195 | mod tests { | 207 | mod tests { |
196 | use syntax::SourceFile; | 208 | use syntax::SourceFile; |
197 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 209 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range, mark}; |
198 | 210 | ||
199 | use super::*; | 211 | use super::*; |
200 | 212 | ||
@@ -771,4 +783,42 @@ fn foo() { | |||
771 | ", | 783 | ", |
772 | ); | 784 | ); |
773 | } | 785 | } |
786 | |||
787 | #[test] | ||
788 | fn join_string_literal() { | ||
789 | mark::check!(join_string_literal); | ||
790 | check_join_lines( | ||
791 | r#" | ||
792 | fn main() { | ||
793 | $0" | ||
794 | hello | ||
795 | "; | ||
796 | } | ||
797 | "#, | ||
798 | r#" | ||
799 | fn main() { | ||
800 | $0"hello | ||
801 | "; | ||
802 | } | ||
803 | "#, | ||
804 | ); | ||
805 | |||
806 | check_join_lines( | ||
807 | r#" | ||
808 | fn main() { | ||
809 | " | ||
810 | $0hello | ||
811 | world | ||
812 | "; | ||
813 | } | ||
814 | "#, | ||
815 | r#" | ||
816 | fn main() { | ||
817 | " | ||
818 | $0hello world | ||
819 | "; | ||
820 | } | ||
821 | "#, | ||
822 | ); | ||
823 | } | ||
774 | } | 824 | } |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 22ddeeae3..1919639a3 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -88,6 +88,8 @@ pub(crate) fn rename_with_semantics( | |||
88 | let def = find_definition(sema, syntax, position)?; | 88 | let def = find_definition(sema, syntax, position)?; |
89 | match def { | 89 | match def { |
90 | Definition::ModuleDef(ModuleDef::Module(module)) => rename_mod(&sema, module, new_name), | 90 | Definition::ModuleDef(ModuleDef::Module(module)) => rename_mod(&sema, module, new_name), |
91 | Definition::SelfType(_) => bail!("Cannot rename `Self`"), | ||
92 | Definition::ModuleDef(ModuleDef::BuiltinType(_)) => bail!("Cannot rename builtin type"), | ||
91 | def => rename_reference(sema, def, new_name), | 93 | def => rename_reference(sema, def, new_name), |
92 | } | 94 | } |
93 | } | 95 | } |
@@ -122,7 +124,7 @@ fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { | |||
122 | Ok(IdentifierKind::Lifetime) | 124 | Ok(IdentifierKind::Lifetime) |
123 | } | 125 | } |
124 | (SyntaxKind::LIFETIME_IDENT, _) => { | 126 | (SyntaxKind::LIFETIME_IDENT, _) => { |
125 | bail!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name) | 127 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) |
126 | } | 128 | } |
127 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), | 129 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), |
128 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), | 130 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), |
@@ -162,119 +164,6 @@ fn find_definition( | |||
162 | .ok_or_else(|| format_err!("No references found at position")) | 164 | .ok_or_else(|| format_err!("No references found at position")) |
163 | } | 165 | } |
164 | 166 | ||
165 | fn source_edit_from_references( | ||
166 | _sema: &Semantics<RootDatabase>, | ||
167 | file_id: FileId, | ||
168 | references: &[FileReference], | ||
169 | def: Definition, | ||
170 | new_name: &str, | ||
171 | ) -> (FileId, TextEdit) { | ||
172 | let mut edit = TextEdit::builder(); | ||
173 | for reference in references { | ||
174 | let (range, replacement) = match &reference.name { | ||
175 | // if the ranges differ then the node is inside a macro call, we can't really attempt | ||
176 | // to make special rewrites like shorthand syntax and such, so just rename the node in | ||
177 | // the macro input | ||
178 | ast::NameLike::NameRef(name_ref) | ||
179 | if name_ref.syntax().text_range() == reference.range => | ||
180 | { | ||
181 | source_edit_from_name_ref(name_ref, new_name, def) | ||
182 | } | ||
183 | ast::NameLike::Name(name) if name.syntax().text_range() == reference.range => { | ||
184 | source_edit_from_name(name, new_name) | ||
185 | } | ||
186 | _ => None, | ||
187 | } | ||
188 | .unwrap_or_else(|| (reference.range, new_name.to_string())); | ||
189 | edit.replace(range, replacement); | ||
190 | } | ||
191 | (file_id, edit.finish()) | ||
192 | } | ||
193 | |||
194 | fn source_edit_from_name(name: &ast::Name, new_name: &str) -> Option<(TextRange, String)> { | ||
195 | if let Some(_) = ast::RecordPatField::for_field_name(name) { | ||
196 | if let Some(ident_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { | ||
197 | return Some(( | ||
198 | TextRange::empty(ident_pat.syntax().text_range().start()), | ||
199 | format!("{}: ", new_name), | ||
200 | )); | ||
201 | } | ||
202 | } | ||
203 | None | ||
204 | } | ||
205 | |||
206 | fn source_edit_from_name_ref( | ||
207 | name_ref: &ast::NameRef, | ||
208 | new_name: &str, | ||
209 | def: Definition, | ||
210 | ) -> Option<(TextRange, String)> { | ||
211 | if let Some(record_field) = ast::RecordExprField::for_name_ref(name_ref) { | ||
212 | let rcf_name_ref = record_field.name_ref(); | ||
213 | let rcf_expr = record_field.expr(); | ||
214 | match (rcf_name_ref, rcf_expr.and_then(|it| it.name_ref())) { | ||
215 | // field: init-expr, check if we can use a field init shorthand | ||
216 | (Some(field_name), Some(init)) => { | ||
217 | if field_name == *name_ref { | ||
218 | if init.text() == new_name { | ||
219 | mark::hit!(test_rename_field_put_init_shorthand); | ||
220 | // same names, we can use a shorthand here instead. | ||
221 | // we do not want to erase attributes hence this range start | ||
222 | let s = field_name.syntax().text_range().start(); | ||
223 | let e = record_field.syntax().text_range().end(); | ||
224 | return Some((TextRange::new(s, e), new_name.to_owned())); | ||
225 | } | ||
226 | } else if init == *name_ref { | ||
227 | if field_name.text() == new_name { | ||
228 | mark::hit!(test_rename_local_put_init_shorthand); | ||
229 | // same names, we can use a shorthand here instead. | ||
230 | // we do not want to erase attributes hence this range start | ||
231 | let s = field_name.syntax().text_range().start(); | ||
232 | let e = record_field.syntax().text_range().end(); | ||
233 | return Some((TextRange::new(s, e), new_name.to_owned())); | ||
234 | } | ||
235 | } | ||
236 | None | ||
237 | } | ||
238 | // init shorthand | ||
239 | // FIXME: instead of splitting the shorthand, recursively trigger a rename of the | ||
240 | // other name https://github.com/rust-analyzer/rust-analyzer/issues/6547 | ||
241 | (None, Some(_)) if matches!(def, Definition::Field(_)) => { | ||
242 | mark::hit!(test_rename_field_in_field_shorthand); | ||
243 | let s = name_ref.syntax().text_range().start(); | ||
244 | Some((TextRange::empty(s), format!("{}: ", new_name))) | ||
245 | } | ||
246 | (None, Some(_)) if matches!(def, Definition::Local(_)) => { | ||
247 | mark::hit!(test_rename_local_in_field_shorthand); | ||
248 | let s = name_ref.syntax().text_range().end(); | ||
249 | Some((TextRange::empty(s), format!(": {}", new_name))) | ||
250 | } | ||
251 | _ => None, | ||
252 | } | ||
253 | } else if let Some(record_field) = ast::RecordPatField::for_field_name_ref(name_ref) { | ||
254 | let rcf_name_ref = record_field.name_ref(); | ||
255 | let rcf_pat = record_field.pat(); | ||
256 | match (rcf_name_ref, rcf_pat) { | ||
257 | // field: rename | ||
258 | (Some(field_name), Some(ast::Pat::IdentPat(pat))) if field_name == *name_ref => { | ||
259 | // field name is being renamed | ||
260 | if pat.name().map_or(false, |it| it.text() == new_name) { | ||
261 | mark::hit!(test_rename_field_put_init_shorthand_pat); | ||
262 | // same names, we can use a shorthand here instead/ | ||
263 | // we do not want to erase attributes hence this range start | ||
264 | let s = field_name.syntax().text_range().start(); | ||
265 | let e = record_field.syntax().text_range().end(); | ||
266 | Some((TextRange::new(s, e), pat.to_string())) | ||
267 | } else { | ||
268 | None | ||
269 | } | ||
270 | } | ||
271 | _ => None, | ||
272 | } | ||
273 | } else { | ||
274 | None | ||
275 | } | ||
276 | } | ||
277 | |||
278 | fn rename_mod( | 167 | fn rename_mod( |
279 | sema: &Semantics<RootDatabase>, | 168 | sema: &Semantics<RootDatabase>, |
280 | module: Module, | 169 | module: Module, |
@@ -308,18 +197,75 @@ fn rename_mod( | |||
308 | TextEdit::replace(name.syntax().text_range(), new_name.to_string()), | 197 | TextEdit::replace(name.syntax().text_range(), new_name.to_string()), |
309 | ), | 198 | ), |
310 | _ => unreachable!(), | 199 | _ => unreachable!(), |
311 | }; | 200 | } |
312 | } | 201 | } |
313 | let def = Definition::ModuleDef(ModuleDef::Module(module)); | 202 | let def = Definition::ModuleDef(ModuleDef::Module(module)); |
314 | let usages = def.usages(sema).all(); | 203 | let usages = def.usages(sema).all(); |
315 | let ref_edits = usages.iter().map(|(&file_id, references)| { | 204 | let ref_edits = usages.iter().map(|(&file_id, references)| { |
316 | source_edit_from_references(sema, file_id, references, def, new_name) | 205 | (file_id, source_edit_from_references(references, def, new_name)) |
317 | }); | 206 | }); |
318 | source_change.extend(ref_edits); | 207 | source_change.extend(ref_edits); |
319 | 208 | ||
320 | Ok(source_change) | 209 | Ok(source_change) |
321 | } | 210 | } |
322 | 211 | ||
212 | fn rename_reference( | ||
213 | sema: &Semantics<RootDatabase>, | ||
214 | def: Definition, | ||
215 | new_name: &str, | ||
216 | ) -> RenameResult<SourceChange> { | ||
217 | let ident_kind = check_identifier(new_name)?; | ||
218 | |||
219 | let def_is_lbl_or_lt = matches!( | ||
220 | def, | ||
221 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) | ||
222 | ); | ||
223 | match (ident_kind, def) { | ||
224 | (IdentifierKind::ToSelf, _) | ||
225 | | (IdentifierKind::Underscore, _) | ||
226 | | (IdentifierKind::Ident, _) | ||
227 | if def_is_lbl_or_lt => | ||
228 | { | ||
229 | mark::hit!(rename_not_a_lifetime_ident_ref); | ||
230 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) | ||
231 | } | ||
232 | (IdentifierKind::Lifetime, _) if def_is_lbl_or_lt => mark::hit!(rename_lifetime), | ||
233 | (IdentifierKind::Lifetime, _) => { | ||
234 | mark::hit!(rename_not_an_ident_ref); | ||
235 | bail!("Invalid name `{}`: not an identifier", new_name) | ||
236 | } | ||
237 | (IdentifierKind::ToSelf, Definition::Local(local)) if local.is_self(sema.db) => { | ||
238 | // no-op | ||
239 | mark::hit!(rename_self_to_self); | ||
240 | return Ok(SourceChange::default()); | ||
241 | } | ||
242 | (ident_kind, Definition::Local(local)) if local.is_self(sema.db) => { | ||
243 | mark::hit!(rename_self_to_param); | ||
244 | return rename_self_to_param(sema, local, new_name, ident_kind); | ||
245 | } | ||
246 | (IdentifierKind::ToSelf, Definition::Local(local)) => { | ||
247 | mark::hit!(rename_to_self); | ||
248 | return rename_to_self(sema, local); | ||
249 | } | ||
250 | (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name), | ||
251 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), | ||
252 | } | ||
253 | |||
254 | let usages = def.usages(sema).all(); | ||
255 | if !usages.is_empty() && ident_kind == IdentifierKind::Underscore { | ||
256 | mark::hit!(rename_underscore_multiple); | ||
257 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); | ||
258 | } | ||
259 | let mut source_change = SourceChange::default(); | ||
260 | source_change.extend(usages.iter().map(|(&file_id, references)| { | ||
261 | (file_id, source_edit_from_references(&references, def, new_name)) | ||
262 | })); | ||
263 | |||
264 | let (file_id, edit) = source_edit_from_def(sema, def, new_name)?; | ||
265 | source_change.insert_source_edit(file_id, edit); | ||
266 | Ok(source_change) | ||
267 | } | ||
268 | |||
323 | fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> { | 269 | fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> { |
324 | if never!(local.is_self(sema.db)) { | 270 | if never!(local.is_self(sema.db)) { |
325 | bail!("rename_to_self invoked on self"); | 271 | bail!("rename_to_self invoked on self"); |
@@ -384,7 +330,7 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe | |||
384 | let usages = def.usages(sema).all(); | 330 | let usages = def.usages(sema).all(); |
385 | let mut source_change = SourceChange::default(); | 331 | let mut source_change = SourceChange::default(); |
386 | source_change.extend(usages.iter().map(|(&file_id, references)| { | 332 | source_change.extend(usages.iter().map(|(&file_id, references)| { |
387 | source_edit_from_references(sema, file_id, references, def, "self") | 333 | (file_id, source_edit_from_references(references, def, "self")) |
388 | })); | 334 | })); |
389 | source_change.insert_source_edit( | 335 | source_change.insert_source_edit( |
390 | file_id.original_file(sema.db), | 336 | file_id.original_file(sema.db), |
@@ -394,29 +340,6 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe | |||
394 | Ok(source_change) | 340 | Ok(source_change) |
395 | } | 341 | } |
396 | 342 | ||
397 | fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Option<TextEdit> { | ||
398 | fn target_type_name(impl_def: &ast::Impl) -> Option<String> { | ||
399 | if let Some(ast::Type::PathType(p)) = impl_def.self_ty() { | ||
400 | return Some(p.path()?.segment()?.name_ref()?.text().to_string()); | ||
401 | } | ||
402 | None | ||
403 | } | ||
404 | |||
405 | let impl_def = self_param.syntax().ancestors().find_map(|it| ast::Impl::cast(it))?; | ||
406 | let type_name = target_type_name(&impl_def)?; | ||
407 | |||
408 | let mut replacement_text = String::from(new_name); | ||
409 | replacement_text.push_str(": "); | ||
410 | match (self_param.amp_token(), self_param.mut_token()) { | ||
411 | (None, None) => (), | ||
412 | (Some(_), None) => replacement_text.push('&'), | ||
413 | (_, Some(_)) => replacement_text.push_str("&mut "), | ||
414 | }; | ||
415 | replacement_text.push_str(type_name.as_str()); | ||
416 | |||
417 | Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text)) | ||
418 | } | ||
419 | |||
420 | fn rename_self_to_param( | 343 | fn rename_self_to_param( |
421 | sema: &Semantics<RootDatabase>, | 344 | sema: &Semantics<RootDatabase>, |
422 | local: hir::Local, | 345 | local: hir::Local, |
@@ -441,66 +364,143 @@ fn rename_self_to_param( | |||
441 | let mut source_change = SourceChange::default(); | 364 | let mut source_change = SourceChange::default(); |
442 | source_change.insert_source_edit(file_id.original_file(sema.db), edit); | 365 | source_change.insert_source_edit(file_id.original_file(sema.db), edit); |
443 | source_change.extend(usages.iter().map(|(&file_id, references)| { | 366 | source_change.extend(usages.iter().map(|(&file_id, references)| { |
444 | source_edit_from_references(sema, file_id, &references, def, new_name) | 367 | (file_id, source_edit_from_references(&references, def, new_name)) |
445 | })); | 368 | })); |
446 | Ok(source_change) | 369 | Ok(source_change) |
447 | } | 370 | } |
448 | 371 | ||
449 | fn rename_reference( | 372 | fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Option<TextEdit> { |
450 | sema: &Semantics<RootDatabase>, | 373 | fn target_type_name(impl_def: &ast::Impl) -> Option<String> { |
374 | if let Some(ast::Type::PathType(p)) = impl_def.self_ty() { | ||
375 | return Some(p.path()?.segment()?.name_ref()?.text().to_string()); | ||
376 | } | ||
377 | None | ||
378 | } | ||
379 | |||
380 | let impl_def = self_param.syntax().ancestors().find_map(|it| ast::Impl::cast(it))?; | ||
381 | let type_name = target_type_name(&impl_def)?; | ||
382 | |||
383 | let mut replacement_text = String::from(new_name); | ||
384 | replacement_text.push_str(": "); | ||
385 | match (self_param.amp_token(), self_param.mut_token()) { | ||
386 | (Some(_), None) => replacement_text.push('&'), | ||
387 | (Some(_), Some(_)) => replacement_text.push_str("&mut "), | ||
388 | (_, _) => (), | ||
389 | }; | ||
390 | replacement_text.push_str(type_name.as_str()); | ||
391 | |||
392 | Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text)) | ||
393 | } | ||
394 | |||
395 | fn source_edit_from_references( | ||
396 | references: &[FileReference], | ||
451 | def: Definition, | 397 | def: Definition, |
452 | new_name: &str, | 398 | new_name: &str, |
453 | ) -> RenameResult<SourceChange> { | 399 | ) -> TextEdit { |
454 | let ident_kind = check_identifier(new_name)?; | 400 | let mut edit = TextEdit::builder(); |
455 | 401 | for reference in references { | |
456 | let def_is_lbl_or_lt = matches!( | 402 | let (range, replacement) = match &reference.name { |
457 | def, | 403 | // if the ranges differ then the node is inside a macro call, we can't really attempt |
458 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) | 404 | // to make special rewrites like shorthand syntax and such, so just rename the node in |
459 | ); | 405 | // the macro input |
460 | match (ident_kind, def) { | 406 | ast::NameLike::NameRef(name_ref) |
461 | (IdentifierKind::ToSelf, _) | 407 | if name_ref.syntax().text_range() == reference.range => |
462 | | (IdentifierKind::Underscore, _) | 408 | { |
463 | | (IdentifierKind::Ident, _) | 409 | source_edit_from_name_ref(name_ref, new_name, def) |
464 | if def_is_lbl_or_lt => | 410 | } |
465 | { | 411 | ast::NameLike::Name(name) if name.syntax().text_range() == reference.range => { |
466 | mark::hit!(rename_not_a_lifetime_ident_ref); | 412 | source_edit_from_name(name, new_name) |
467 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) | 413 | } |
468 | } | 414 | _ => None, |
469 | (IdentifierKind::Lifetime, _) if def_is_lbl_or_lt => mark::hit!(rename_lifetime), | ||
470 | (IdentifierKind::Lifetime, _) => { | ||
471 | mark::hit!(rename_not_an_ident_ref); | ||
472 | bail!("Invalid name `{}`: not an identifier", new_name) | ||
473 | } | ||
474 | (IdentifierKind::ToSelf, Definition::Local(local)) if local.is_self(sema.db) => { | ||
475 | // no-op | ||
476 | mark::hit!(rename_self_to_self); | ||
477 | return Ok(SourceChange::default()); | ||
478 | } | ||
479 | (ident_kind, Definition::Local(local)) if local.is_self(sema.db) => { | ||
480 | mark::hit!(rename_self_to_param); | ||
481 | return rename_self_to_param(sema, local, new_name, ident_kind); | ||
482 | } | ||
483 | (IdentifierKind::ToSelf, Definition::Local(local)) => { | ||
484 | mark::hit!(rename_to_self); | ||
485 | return rename_to_self(sema, local); | ||
486 | } | 415 | } |
487 | (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name), | 416 | .unwrap_or_else(|| (reference.range, new_name.to_string())); |
488 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), | 417 | edit.replace(range, replacement); |
489 | } | 418 | } |
419 | edit.finish() | ||
420 | } | ||
490 | 421 | ||
491 | let usages = def.usages(sema).all(); | 422 | fn source_edit_from_name(name: &ast::Name, new_name: &str) -> Option<(TextRange, String)> { |
492 | if !usages.is_empty() && ident_kind == IdentifierKind::Underscore { | 423 | if let Some(_) = ast::RecordPatField::for_field_name(name) { |
493 | mark::hit!(rename_underscore_multiple); | 424 | if let Some(ident_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { |
494 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); | 425 | return Some(( |
426 | TextRange::empty(ident_pat.syntax().text_range().start()), | ||
427 | [new_name, ": "].concat(), | ||
428 | )); | ||
429 | } | ||
495 | } | 430 | } |
496 | let mut source_change = SourceChange::default(); | 431 | None |
497 | source_change.extend(usages.iter().map(|(&file_id, references)| { | 432 | } |
498 | source_edit_from_references(sema, file_id, &references, def, new_name) | ||
499 | })); | ||
500 | 433 | ||
501 | let (file_id, edit) = source_edit_from_def(sema, def, new_name)?; | 434 | fn source_edit_from_name_ref( |
502 | source_change.insert_source_edit(file_id, edit); | 435 | name_ref: &ast::NameRef, |
503 | Ok(source_change) | 436 | new_name: &str, |
437 | def: Definition, | ||
438 | ) -> Option<(TextRange, String)> { | ||
439 | if let Some(record_field) = ast::RecordExprField::for_name_ref(name_ref) { | ||
440 | let rcf_name_ref = record_field.name_ref(); | ||
441 | let rcf_expr = record_field.expr(); | ||
442 | match (rcf_name_ref, rcf_expr.and_then(|it| it.name_ref())) { | ||
443 | // field: init-expr, check if we can use a field init shorthand | ||
444 | (Some(field_name), Some(init)) => { | ||
445 | if field_name == *name_ref { | ||
446 | if init.text() == new_name { | ||
447 | mark::hit!(test_rename_field_put_init_shorthand); | ||
448 | // same names, we can use a shorthand here instead. | ||
449 | // we do not want to erase attributes hence this range start | ||
450 | let s = field_name.syntax().text_range().start(); | ||
451 | let e = record_field.syntax().text_range().end(); | ||
452 | return Some((TextRange::new(s, e), new_name.to_owned())); | ||
453 | } | ||
454 | } else if init == *name_ref { | ||
455 | if field_name.text() == new_name { | ||
456 | mark::hit!(test_rename_local_put_init_shorthand); | ||
457 | // same names, we can use a shorthand here instead. | ||
458 | // we do not want to erase attributes hence this range start | ||
459 | let s = field_name.syntax().text_range().start(); | ||
460 | let e = record_field.syntax().text_range().end(); | ||
461 | return Some((TextRange::new(s, e), new_name.to_owned())); | ||
462 | } | ||
463 | } | ||
464 | None | ||
465 | } | ||
466 | // init shorthand | ||
467 | // FIXME: instead of splitting the shorthand, recursively trigger a rename of the | ||
468 | // other name https://github.com/rust-analyzer/rust-analyzer/issues/6547 | ||
469 | (None, Some(_)) if matches!(def, Definition::Field(_)) => { | ||
470 | mark::hit!(test_rename_field_in_field_shorthand); | ||
471 | let s = name_ref.syntax().text_range().start(); | ||
472 | Some((TextRange::empty(s), format!("{}: ", new_name))) | ||
473 | } | ||
474 | (None, Some(_)) if matches!(def, Definition::Local(_)) => { | ||
475 | mark::hit!(test_rename_local_in_field_shorthand); | ||
476 | let s = name_ref.syntax().text_range().end(); | ||
477 | Some((TextRange::empty(s), format!(": {}", new_name))) | ||
478 | } | ||
479 | _ => None, | ||
480 | } | ||
481 | } else if let Some(record_field) = ast::RecordPatField::for_field_name_ref(name_ref) { | ||
482 | let rcf_name_ref = record_field.name_ref(); | ||
483 | let rcf_pat = record_field.pat(); | ||
484 | match (rcf_name_ref, rcf_pat) { | ||
485 | // field: rename | ||
486 | (Some(field_name), Some(ast::Pat::IdentPat(pat))) if field_name == *name_ref => { | ||
487 | // field name is being renamed | ||
488 | if pat.name().map_or(false, |it| it.text() == new_name) { | ||
489 | mark::hit!(test_rename_field_put_init_shorthand_pat); | ||
490 | // same names, we can use a shorthand here instead/ | ||
491 | // we do not want to erase attributes hence this range start | ||
492 | let s = field_name.syntax().text_range().start(); | ||
493 | let e = record_field.syntax().text_range().end(); | ||
494 | Some((TextRange::new(s, e), pat.to_string())) | ||
495 | } else { | ||
496 | None | ||
497 | } | ||
498 | } | ||
499 | _ => None, | ||
500 | } | ||
501 | } else { | ||
502 | None | ||
503 | } | ||
504 | } | 504 | } |
505 | 505 | ||
506 | fn source_edit_from_def( | 506 | fn source_edit_from_def( |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 1e7baed20..65f60891e 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -189,7 +189,7 @@ pub(crate) fn doc_owner_to_def( | |||
189 | ) -> Option<Definition> { | 189 | ) -> Option<Definition> { |
190 | let res: hir::ModuleDef = match_ast! { | 190 | let res: hir::ModuleDef = match_ast! { |
191 | match item { | 191 | match item { |
192 | ast::SourceFile(it) => sema.scope(&item).module()?.into(), | 192 | ast::SourceFile(_it) => sema.scope(&item).module()?.into(), |
193 | ast::Fn(it) => sema.to_def(&it)?.into(), | 193 | ast::Fn(it) => sema.to_def(&it)?.into(), |
194 | ast::Struct(it) => sema.to_def(&it)?.into(), | 194 | ast::Struct(it) => sema.to_def(&it)?.into(), |
195 | ast::Enum(it) => sema.to_def(&it)?.into(), | 195 | ast::Enum(it) => sema.to_def(&it)?.into(), |
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs index 8e9ea4fad..a08b55ebb 100644 --- a/crates/ide_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs | |||
@@ -31,6 +31,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
31 | return None; | 31 | return None; |
32 | } | 32 | } |
33 | mark::hit!(add_turbo_fish_after_call); | 33 | mark::hit!(add_turbo_fish_after_call); |
34 | mark::hit!(add_type_ascription_after_call); | ||
34 | arg_list.l_paren_token()?.prev_token().filter(|it| it.kind() == SyntaxKind::IDENT) | 35 | arg_list.l_paren_token()?.prev_token().filter(|it| it.kind() == SyntaxKind::IDENT) |
35 | })?; | 36 | })?; |
36 | let next_token = ident.next_token()?; | 37 | let next_token = ident.next_token()?; |
@@ -52,6 +53,24 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
52 | mark::hit!(add_turbo_fish_non_generic); | 53 | mark::hit!(add_turbo_fish_non_generic); |
53 | return None; | 54 | return None; |
54 | } | 55 | } |
56 | |||
57 | if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() { | ||
58 | if let_stmt.colon_token().is_none() { | ||
59 | let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end(); | ||
60 | acc.add( | ||
61 | AssistId("add_type_ascription", AssistKind::RefactorRewrite), | ||
62 | "Add `: _` before assignment operator", | ||
63 | ident.text_range(), | ||
64 | |builder| match ctx.config.snippet_cap { | ||
65 | Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"), | ||
66 | None => builder.insert(type_pos, ": _"), | ||
67 | }, | ||
68 | )? | ||
69 | } else { | ||
70 | mark::hit!(add_type_ascription_already_typed); | ||
71 | } | ||
72 | } | ||
73 | |||
55 | acc.add( | 74 | acc.add( |
56 | AssistId("add_turbo_fish", AssistKind::RefactorRewrite), | 75 | AssistId("add_turbo_fish", AssistKind::RefactorRewrite), |
57 | "Add `::<>`", | 76 | "Add `::<>`", |
@@ -65,7 +84,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
65 | 84 | ||
66 | #[cfg(test)] | 85 | #[cfg(test)] |
67 | mod tests { | 86 | mod tests { |
68 | use crate::tests::{check_assist, check_assist_not_applicable}; | 87 | use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable}; |
69 | 88 | ||
70 | use super::*; | 89 | use super::*; |
71 | use test_utils::mark; | 90 | use test_utils::mark; |
@@ -161,4 +180,91 @@ fn main() { | |||
161 | "#, | 180 | "#, |
162 | ); | 181 | ); |
163 | } | 182 | } |
183 | |||
184 | #[test] | ||
185 | fn add_type_ascription_function() { | ||
186 | check_assist_by_label( | ||
187 | add_turbo_fish, | ||
188 | r#" | ||
189 | fn make<T>() -> T {} | ||
190 | fn main() { | ||
191 | let x = make$0(); | ||
192 | } | ||
193 | "#, | ||
194 | r#" | ||
195 | fn make<T>() -> T {} | ||
196 | fn main() { | ||
197 | let x: ${0:_} = make(); | ||
198 | } | ||
199 | "#, | ||
200 | "Add `: _` before assignment operator", | ||
201 | ); | ||
202 | } | ||
203 | |||
204 | #[test] | ||
205 | fn add_type_ascription_after_call() { | ||
206 | mark::check!(add_type_ascription_after_call); | ||
207 | check_assist_by_label( | ||
208 | add_turbo_fish, | ||
209 | r#" | ||
210 | fn make<T>() -> T {} | ||
211 | fn main() { | ||
212 | let x = make()$0; | ||
213 | } | ||
214 | "#, | ||
215 | r#" | ||
216 | fn make<T>() -> T {} | ||
217 | fn main() { | ||
218 | let x: ${0:_} = make(); | ||
219 | } | ||
220 | "#, | ||
221 | "Add `: _` before assignment operator", | ||
222 | ); | ||
223 | } | ||
224 | |||
225 | #[test] | ||
226 | fn add_type_ascription_method() { | ||
227 | check_assist_by_label( | ||
228 | add_turbo_fish, | ||
229 | r#" | ||
230 | struct S; | ||
231 | impl S { | ||
232 | fn make<T>(&self) -> T {} | ||
233 | } | ||
234 | fn main() { | ||
235 | let x = S.make$0(); | ||
236 | } | ||
237 | "#, | ||
238 | r#" | ||
239 | struct S; | ||
240 | impl S { | ||
241 | fn make<T>(&self) -> T {} | ||
242 | } | ||
243 | fn main() { | ||
244 | let x: ${0:_} = S.make(); | ||
245 | } | ||
246 | "#, | ||
247 | "Add `: _` before assignment operator", | ||
248 | ); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn add_type_ascription_already_typed() { | ||
253 | mark::check!(add_type_ascription_already_typed); | ||
254 | check_assist( | ||
255 | add_turbo_fish, | ||
256 | r#" | ||
257 | fn make<T>() -> T {} | ||
258 | fn main() { | ||
259 | let x: () = make$0(); | ||
260 | } | ||
261 | "#, | ||
262 | r#" | ||
263 | fn make<T>() -> T {} | ||
264 | fn main() { | ||
265 | let x: () = make::<${0:_}>(); | ||
266 | } | ||
267 | "#, | ||
268 | ); | ||
269 | } | ||
164 | } | 270 | } |
diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index 6997ea048..128b1eb56 100644 --- a/crates/ide_assists/src/handlers/apply_demorgan.rs +++ b/crates/ide_assists/src/handlers/apply_demorgan.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | use syntax::ast::{self, AstNode}; | 1 | use syntax::ast::{self, AstNode}; |
2 | use test_utils::mark; | ||
2 | 3 | ||
3 | use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; | 4 | use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; |
4 | 5 | ||
@@ -43,9 +44,36 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
43 | "Apply De Morgan's law", | 44 | "Apply De Morgan's law", |
44 | op_range, | 45 | op_range, |
45 | |edit| { | 46 | |edit| { |
47 | let paren_expr = expr.syntax().parent().and_then(|parent| ast::ParenExpr::cast(parent)); | ||
48 | |||
49 | let neg_expr = paren_expr | ||
50 | .clone() | ||
51 | .and_then(|paren_expr| paren_expr.syntax().parent()) | ||
52 | .and_then(|parent| ast::PrefixExpr::cast(parent)) | ||
53 | .and_then(|prefix_expr| { | ||
54 | if prefix_expr.op_kind().unwrap() == ast::PrefixOp::Not { | ||
55 | Some(prefix_expr) | ||
56 | } else { | ||
57 | None | ||
58 | } | ||
59 | }); | ||
60 | |||
46 | edit.replace(op_range, opposite_op); | 61 | edit.replace(op_range, opposite_op); |
47 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); | 62 | |
48 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); | 63 | if let Some(paren_expr) = paren_expr { |
64 | edit.replace(lhs_range, not_lhs.syntax().text()); | ||
65 | edit.replace(rhs_range, not_rhs.syntax().text()); | ||
66 | if let Some(neg_expr) = neg_expr { | ||
67 | mark::hit!(demorgan_double_negation); | ||
68 | edit.replace(neg_expr.op_token().unwrap().text_range(), ""); | ||
69 | } else { | ||
70 | mark::hit!(demorgan_double_parens); | ||
71 | edit.replace(paren_expr.l_paren_token().unwrap().text_range(), "!("); | ||
72 | } | ||
73 | } else { | ||
74 | edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); | ||
75 | edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); | ||
76 | } | ||
49 | }, | 77 | }, |
50 | ) | 78 | ) |
51 | } | 79 | } |
@@ -62,6 +90,7 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> { | |||
62 | #[cfg(test)] | 90 | #[cfg(test)] |
63 | mod tests { | 91 | mod tests { |
64 | use ide_db::helpers::FamousDefs; | 92 | use ide_db::helpers::FamousDefs; |