diff options
271 files changed, 18671 insertions, 7625 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dddc82f80..b5160eaa3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md | |||
@@ -13,12 +13,9 @@ Forum for questions: https://users.rust-lang.org/c/ide/14 | |||
13 | 13 | ||
14 | Before submitting, please make sure that you're not running into one of these known issues: | 14 | Before submitting, please make sure that you're not running into one of these known issues: |
15 | 15 | ||
16 | 1. local imports (`use` statements) don't work: #1165 | 16 | 1. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file) |
17 | 2. local items don't work: #1559 | 17 | 2. some settings are required for procedural macro and build script support (`rust-analyzer.cargo.loadOutDirsFromCheck`, `rust-analyzer.procMacro.enable`): #6448 |
18 | 3. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file) | 18 | 3. some platform-specific imports are not resolved: #6038 |
19 | 4. some settings are required for procedural macro and build script support (`rust-analyzer.cargo.loadOutDirsFromCheck`, `rust-analyzer.procMacro.enable`): #6448 | ||
20 | 5. some platform-specific imports are not resolved: #6038 | ||
21 | 6. the official `rust-lang.rust` VS Code extension conflicts with `rust-analyzer`: #6463 | ||
22 | 19 | ||
23 | Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3. | 20 | Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3. |
24 | --> | 21 | --> |
diff --git a/Cargo.lock b/Cargo.lock index dbd7a746e..b1fef2e80 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" |
@@ -107,9 +107,18 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | |||
107 | 107 | ||
108 | [[package]] | 108 | [[package]] |
109 | name = "byteorder" | 109 | name = "byteorder" |
110 | version = "1.4.2" | 110 | version = "1.4.3" |
111 | source = "registry+https://github.com/rust-lang/crates.io-index" | 111 | source = "registry+https://github.com/rust-lang/crates.io-index" |
112 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" | 112 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" |
113 | |||
114 | [[package]] | ||
115 | name = "camino" | ||
116 | version = "1.0.2" | ||
117 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
118 | checksum = "cd065703998b183ed0b348a22555691373a9345a1431141e5778b48bb17e4703" | ||
119 | dependencies = [ | ||
120 | "serde", | ||
121 | ] | ||
113 | 122 | ||
114 | [[package]] | 123 | [[package]] |
115 | name = "cargo-platform" | 124 | name = "cargo-platform" |
@@ -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.60.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 = "ab0f74445d4fbeaf0217bc1d23978cc73b95b28e8a738b81894580dd646822d2" |
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.60.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 = "294b1fc6210a5b3bd06c1d01dda48a581e2cafec80b8d659139ce45456644be2" |
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.60.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 = "1b9386936070be4545bfa22b094b7065af79aa2aeaccc945438f1c5ffe74c30a" |
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.60.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 = "7c12a1ec7e850b50a049f27ef9cf5df3056bbd1acbb3eeb44d024e501a641f3a" |
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", |
@@ -222,15 +232,6 @@ dependencies = [ | |||
222 | ] | 232 | ] |
223 | 233 | ||
224 | [[package]] | 234 | [[package]] |
225 | name = "cmake" | ||
226 | version = "0.1.45" | ||
227 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
228 | checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" | ||
229 | dependencies = [ | ||
230 | "cc", | ||
231 | ] | ||
232 | |||
233 | [[package]] | ||
234 | name = "countme" | 235 | name = "countme" |
235 | version = "2.0.4" | 236 | version = "2.0.4" |
236 | source = "registry+https://github.com/rust-lang/crates.io-index" | 237 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -242,6 +243,12 @@ dependencies = [ | |||
242 | ] | 243 | ] |
243 | 244 | ||
244 | [[package]] | 245 | [[package]] |
246 | name = "cov-mark" | ||
247 | version = "1.1.0" | ||
248 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
249 | checksum = "9ffa3d3e0138386cd4361f63537765cac7ee40698028844635a54495a92f67f3" | ||
250 | |||
251 | [[package]] | ||
245 | name = "crc32fast" | 252 | name = "crc32fast" |
246 | version = "1.2.1" | 253 | version = "1.2.1" |
247 | source = "registry+https://github.com/rust-lang/crates.io-index" | 254 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -475,7 +482,7 @@ dependencies = [ | |||
475 | "hir_def", | 482 | "hir_def", |
476 | "hir_expand", | 483 | "hir_expand", |
477 | "hir_ty", | 484 | "hir_ty", |
478 | "itertools 0.10.0", | 485 | "itertools", |
479 | "log", | 486 | "log", |
480 | "profile", | 487 | "profile", |
481 | "rustc-hash", | 488 | "rustc-hash", |
@@ -491,13 +498,14 @@ dependencies = [ | |||
491 | "anymap", | 498 | "anymap", |
492 | "base_db", | 499 | "base_db", |
493 | "cfg", | 500 | "cfg", |
501 | "cov-mark", | ||
494 | "drop_bomb", | 502 | "drop_bomb", |
495 | "either", | 503 | "either", |
496 | "expect-test", | 504 | "expect-test", |
497 | "fst", | 505 | "fst", |
498 | "hir_expand", | 506 | "hir_expand", |
499 | "indexmap", | 507 | "indexmap", |
500 | "itertools 0.10.0", | 508 | "itertools", |
501 | "la-arena", | 509 | "la-arena", |
502 | "log", | 510 | "log", |
503 | "mbe", | 511 | "mbe", |
@@ -516,7 +524,9 @@ name = "hir_expand" | |||
516 | version = "0.0.0" | 524 | version = "0.0.0" |
517 | dependencies = [ | 525 | dependencies = [ |
518 | "base_db", | 526 | "base_db", |
527 | "cfg", | ||
519 | "either", | 528 | "either", |
529 | "expect-test", | ||
520 | "la-arena", | 530 | "la-arena", |
521 | "log", | 531 | "log", |
522 | "mbe", | 532 | "mbe", |
@@ -537,11 +547,12 @@ dependencies = [ | |||
537 | "chalk-ir", | 547 | "chalk-ir", |
538 | "chalk-recursive", | 548 | "chalk-recursive", |
539 | "chalk-solve", | 549 | "chalk-solve", |
550 | "cov-mark", | ||
540 | "ena", | 551 | "ena", |
541 | "expect-test", | 552 | "expect-test", |
542 | "hir_def", | 553 | "hir_def", |
543 | "hir_expand", | 554 | "hir_expand", |
544 | "itertools 0.10.0", | 555 | "itertools", |
545 | "la-arena", | 556 | "la-arena", |
546 | "log", | 557 | "log", |
547 | "once_cell", | 558 | "once_cell", |
@@ -571,6 +582,7 @@ name = "ide" | |||
571 | version = "0.0.0" | 582 | version = "0.0.0" |
572 | dependencies = [ | 583 | dependencies = [ |
573 | "cfg", | 584 | "cfg", |
585 | "cov-mark", | ||
574 | "either", | 586 | "either", |
575 | "expect-test", | 587 | "expect-test", |
576 | "hir", | 588 | "hir", |
@@ -579,7 +591,7 @@ dependencies = [ | |||
579 | "ide_db", | 591 | "ide_db", |
580 | "ide_ssr", | 592 | "ide_ssr", |
581 | "indexmap", | 593 | "indexmap", |
582 | "itertools 0.10.0", | 594 | "itertools", |
583 | "log", | 595 | "log", |
584 | "oorandom", | 596 | "oorandom", |
585 | "profile", | 597 | "profile", |
@@ -597,11 +609,12 @@ dependencies = [ | |||
597 | name = "ide_assists" | 609 | name = "ide_assists" |
598 | version = "0.0.0" | 610 | version = "0.0.0" |
599 | dependencies = [ | 611 | dependencies = [ |
612 | "cov-mark", | ||
600 | "either", | 613 | "either", |
601 | "expect-test", | 614 | "expect-test", |
602 | "hir", | 615 | "hir", |
603 | "ide_db", | 616 | "ide_db", |
604 | "itertools 0.10.0", | 617 | "itertools", |
605 | "profile", | 618 | "profile", |
606 | "rustc-hash", | 619 | "rustc-hash", |
607 | "stdx", | 620 | "stdx", |
@@ -615,11 +628,12 @@ name = "ide_completion" | |||
615 | version = "0.0.0" | 628 | version = "0.0.0" |
616 | dependencies = [ | 629 | dependencies = [ |
617 | "base_db", | 630 | "base_db", |
631 | "cov-mark", | ||
618 | "either", | 632 | "either", |
619 | "expect-test", | 633 | "expect-test", |
620 | "hir", | 634 | "hir", |
621 | "ide_db", | 635 | "ide_db", |
622 | "itertools 0.10.0", | 636 | "itertools", |
623 | "log", | 637 | "log", |
624 | "profile", | 638 | "profile", |
625 | "rustc-hash", | 639 | "rustc-hash", |
@@ -634,11 +648,12 @@ name = "ide_db" | |||
634 | version = "0.0.0" | 648 | version = "0.0.0" |
635 | dependencies = [ | 649 | dependencies = [ |
636 | "base_db", | 650 | "base_db", |
651 | "cov-mark", | ||
637 | "either", | 652 | "either", |
638 | "expect-test", | 653 | "expect-test", |
639 | "fst", | 654 | "fst", |
640 | "hir", | 655 | "hir", |
641 | "itertools 0.10.0", | 656 | "itertools", |
642 | "log", | 657 | "log", |
643 | "once_cell", | 658 | "once_cell", |
644 | "profile", | 659 | "profile", |
@@ -654,10 +669,11 @@ dependencies = [ | |||
654 | name = "ide_ssr" | 669 | name = "ide_ssr" |
655 | version = "0.0.0" | 670 | version = "0.0.0" |
656 | dependencies = [ | 671 | dependencies = [ |
672 | "cov-mark", | ||
657 | "expect-test", | 673 | "expect-test", |
658 | "hir", | 674 | "hir", |
659 | "ide_db", | 675 | "ide_db", |
660 | "itertools 0.10.0", | 676 | "itertools", |
661 | "rustc-hash", | 677 | "rustc-hash", |
662 | "syntax", | 678 | "syntax", |
663 | "test_utils", | 679 | "test_utils", |
@@ -677,9 +693,9 @@ dependencies = [ | |||
677 | 693 | ||
678 | [[package]] | 694 | [[package]] |
679 | name = "indexmap" | 695 | name = "indexmap" |
680 | version = "1.6.1" | 696 | version = "1.6.2" |
681 | source = "registry+https://github.com/rust-lang/crates.io-index" | 697 | source = "registry+https://github.com/rust-lang/crates.io-index" |
682 | checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" | 698 | checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" |
683 | dependencies = [ | 699 | dependencies = [ |
684 | "autocfg", | 700 | "autocfg", |
685 | "hashbrown", | 701 | "hashbrown", |
@@ -716,15 +732,6 @@ dependencies = [ | |||
716 | 732 | ||
717 | [[package]] | 733 | [[package]] |
718 | name = "itertools" | 734 | 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" | 735 | version = "0.10.0" |
729 | source = "registry+https://github.com/rust-lang/crates.io-index" | 736 | source = "registry+https://github.com/rust-lang/crates.io-index" |
730 | checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" | 737 | checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" |
@@ -788,9 +795,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
788 | 795 | ||
789 | [[package]] | 796 | [[package]] |
790 | name = "libc" | 797 | name = "libc" |
791 | version = "0.2.86" | 798 | version = "0.2.88" |
792 | source = "registry+https://github.com/rust-lang/crates.io-index" | 799 | source = "registry+https://github.com/rust-lang/crates.io-index" |
793 | checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" | 800 | checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" |
794 | 801 | ||
795 | [[package]] | 802 | [[package]] |
796 | name = "libloading" | 803 | name = "libloading" |
@@ -804,11 +811,11 @@ dependencies = [ | |||
804 | 811 | ||
805 | [[package]] | 812 | [[package]] |
806 | name = "libmimalloc-sys" | 813 | name = "libmimalloc-sys" |
807 | version = "0.1.20" | 814 | version = "0.1.21" |
808 | source = "registry+https://github.com/rust-lang/crates.io-index" | 815 | source = "registry+https://github.com/rust-lang/crates.io-index" |
809 | checksum = "e58f42b6424a0ed536678c65fd97cd64b4344bcf86251e284f7c0ce9eee40e64" | 816 | checksum = "2396cf99d2f58611cd69f0efeee4af3d2e2c7b61bed433515029163aa567e65c" |
810 | dependencies = [ | 817 | dependencies = [ |
811 | "cmake", | 818 | "cc", |
812 | ] | 819 | ] |
813 | 820 | ||
814 | [[package]] | 821 | [[package]] |
@@ -873,11 +880,13 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" | |||
873 | name = "mbe" | 880 | name = "mbe" |
874 | version = "0.0.0" | 881 | version = "0.0.0" |
875 | dependencies = [ | 882 | dependencies = [ |
883 | "cov-mark", | ||
876 | "log", | 884 | "log", |
877 | "parser", | 885 | "parser", |
878 | "profile", | 886 | "profile", |
879 | "rustc-hash", | 887 | "rustc-hash", |
880 | "smallvec", | 888 | "smallvec", |
889 | "stdx", | ||
881 | "syntax", | 890 | "syntax", |
882 | "test_utils", | 891 | "test_utils", |
883 | "tt", | 892 | "tt", |
@@ -890,6 +899,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
890 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" | 899 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" |
891 | 900 | ||
892 | [[package]] | 901 | [[package]] |
902 | name = "memmap" | ||
903 | version = "0.7.0" | ||
904 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
905 | checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" | ||
906 | dependencies = [ | ||
907 | "libc", | ||
908 | "winapi", | ||
909 | ] | ||
910 | |||
911 | [[package]] | ||
893 | name = "memmap2" | 912 | name = "memmap2" |
894 | version = "0.2.1" | 913 | version = "0.2.1" |
895 | source = "registry+https://github.com/rust-lang/crates.io-index" | 914 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -909,9 +928,9 @@ dependencies = [ | |||
909 | 928 | ||
910 | [[package]] | 929 | [[package]] |
911 | name = "mimalloc" | 930 | name = "mimalloc" |
912 | version = "0.1.24" | 931 | version = "0.1.25" |
913 | source = "registry+https://github.com/rust-lang/crates.io-index" | 932 | source = "registry+https://github.com/rust-lang/crates.io-index" |
914 | checksum = "757efec188b3d2088949d912e01ea2fe87164ed6376b6c5d7dd4f3ce1668a93d" | 933 | checksum = "1e7c6b11afd1e5e689ac96b6d18b1fc763398fe3d7eed99e8773426bc2033dfb" |
915 | dependencies = [ | 934 | dependencies = [ |
916 | "libmimalloc-sys", | 935 | "libmimalloc-sys", |
917 | ] | 936 | ] |
@@ -1014,9 +1033,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" | |||
1014 | 1033 | ||
1015 | [[package]] | 1034 | [[package]] |
1016 | name = "once_cell" | 1035 | name = "once_cell" |
1017 | version = "1.7.0" | 1036 | version = "1.7.2" |
1018 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1019 | checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a" | 1038 | checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" |
1020 | 1039 | ||
1021 | [[package]] | 1040 | [[package]] |
1022 | name = "oorandom" | 1041 | name = "oorandom" |
@@ -1124,16 +1143,10 @@ dependencies = [ | |||
1124 | ] | 1143 | ] |
1125 | 1144 | ||
1126 | [[package]] | 1145 | [[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" | 1146 | name = "pin-project-lite" |
1134 | version = "0.2.4" | 1147 | version = "0.2.6" |
1135 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1136 | checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" | 1149 | checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" |
1137 | 1150 | ||
1138 | [[package]] | 1151 | [[package]] |
1139 | name = "proc-macro-hack" | 1152 | name = "proc-macro-hack" |
@@ -1158,8 +1171,11 @@ dependencies = [ | |||
1158 | "crossbeam-channel", | 1171 | "crossbeam-channel", |
1159 | "jod-thread", | 1172 | "jod-thread", |
1160 | "log", | 1173 | "log", |
1174 | "memmap", | ||
1175 | "object", | ||
1161 | "serde", | 1176 | "serde", |
1162 | "serde_json", | 1177 | "serde_json", |
1178 | "snap", | ||
1163 | "stdx", | 1179 | "stdx", |
1164 | "tt", | 1180 | "tt", |
1165 | ] | 1181 | ] |
@@ -1206,7 +1222,7 @@ dependencies = [ | |||
1206 | "base_db", | 1222 | "base_db", |
1207 | "cargo_metadata", | 1223 | "cargo_metadata", |
1208 | "cfg", | 1224 | "cfg", |
1209 | "itertools 0.10.0", | 1225 | "itertools", |
1210 | "la-arena", | 1226 | "la-arena", |
1211 | "log", | 1227 | "log", |
1212 | "paths", | 1228 | "paths", |
@@ -1338,7 +1354,7 @@ dependencies = [ | |||
1338 | "ide", | 1354 | "ide", |
1339 | "ide_db", | 1355 | "ide_db", |
1340 | "ide_ssr", | 1356 | "ide_ssr", |
1341 | "itertools 0.10.0", | 1357 | "itertools", |
1342 | "jemallocator", | 1358 | "jemallocator", |
1343 | "jod-thread", | 1359 | "jod-thread", |
1344 | "log", | 1360 | "log", |
@@ -1348,7 +1364,6 @@ dependencies = [ | |||
1348 | "mimalloc", | 1364 | "mimalloc", |
1349 | "oorandom", | 1365 | "oorandom", |
1350 | "parking_lot", | 1366 | "parking_lot", |
1351 | "pico-args", | ||
1352 | "proc_macro_srv", | 1367 | "proc_macro_srv", |
1353 | "profile", | 1368 | "profile", |
1354 | "project_model", | 1369 | "project_model", |
@@ -1370,13 +1385,14 @@ dependencies = [ | |||
1370 | "vfs", | 1385 | "vfs", |
1371 | "vfs-notify", | 1386 | "vfs-notify", |
1372 | "winapi", | 1387 | "winapi", |
1388 | "xflags", | ||
1373 | ] | 1389 | ] |
1374 | 1390 | ||
1375 | [[package]] | 1391 | [[package]] |
1376 | name = "rustc-ap-rustc_lexer" | 1392 | name = "rustc-ap-rustc_lexer" |
1377 | version = "708.0.0" | 1393 | version = "710.0.0" |
1378 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1379 | checksum = "2706fc7106c75eaea49efe9f35f719a6fdfdb95212122ec2b543659406bae7ea" | 1395 | checksum = "b0bba1ca6787b6d4af505b7a940eae9ecb084dd03e07f03bf3ddbf78e738b617" |
1380 | dependencies = [ | 1396 | dependencies = [ |
1381 | "unicode-xid", | 1397 | "unicode-xid", |
1382 | ] | 1398 | ] |
@@ -1470,18 +1486,18 @@ dependencies = [ | |||
1470 | 1486 | ||
1471 | [[package]] | 1487 | [[package]] |
1472 | name = "serde" | 1488 | name = "serde" |
1473 | version = "1.0.123" | 1489 | version = "1.0.124" |
1474 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1475 | checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" | 1491 | checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" |
1476 | dependencies = [ | 1492 | dependencies = [ |
1477 | "serde_derive", | 1493 | "serde_derive", |
1478 | ] | 1494 | ] |
1479 | 1495 | ||
1480 | [[package]] | 1496 | [[package]] |
1481 | name = "serde_derive" | 1497 | name = "serde_derive" |
1482 | version = "1.0.123" | 1498 | version = "1.0.124" |
1483 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1484 | checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" | 1500 | checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" |
1485 | dependencies = [ | 1501 | dependencies = [ |
1486 | "proc-macro2", | 1502 | "proc-macro2", |
1487 | "quote", | 1503 | "quote", |
@@ -1490,9 +1506,9 @@ dependencies = [ | |||
1490 | 1506 | ||
1491 | [[package]] | 1507 | [[package]] |
1492 | name = "serde_json" | 1508 | name = "serde_json" |
1493 | version = "1.0.62" | 1509 | version = "1.0.64" |
1494 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1495 | checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" | 1511 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" |
1496 | dependencies = [ | 1512 | dependencies = [ |
1497 | "indexmap", | 1513 | "indexmap", |
1498 | "itoa", | 1514 | "itoa", |
@@ -1545,6 +1561,12 @@ dependencies = [ | |||
1545 | ] | 1561 | ] |
1546 | 1562 | ||
1547 | [[package]] | 1563 | [[package]] |
1564 | name = "snap" | ||
1565 | version = "1.0.4" | ||
1566 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1567 | checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a" | ||
1568 | |||
1569 | [[package]] | ||
1548 | name = "socket2" | 1570 | name = "socket2" |
1549 | version = "0.3.19" | 1571 | version = "0.3.19" |
1550 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1565,9 +1587,9 @@ dependencies = [ | |||
1565 | 1587 | ||
1566 | [[package]] | 1588 | [[package]] |
1567 | name = "syn" | 1589 | name = "syn" |
1568 | version = "1.0.60" | 1590 | version = "1.0.63" |
1569 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1570 | checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" | 1592 | checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" |
1571 | dependencies = [ | 1593 | dependencies = [ |
1572 | "proc-macro2", | 1594 | "proc-macro2", |
1573 | "quote", | 1595 | "quote", |
@@ -1591,9 +1613,10 @@ name = "syntax" | |||
1591 | version = "0.0.0" | 1613 | version = "0.0.0" |
1592 | dependencies = [ | 1614 | dependencies = [ |
1593 | "arrayvec", | 1615 | "arrayvec", |
1616 | "cov-mark", | ||
1594 | "expect-test", | 1617 | "expect-test", |
1595 | "indexmap", | 1618 | "indexmap", |
1596 | "itertools 0.10.0", | 1619 | "itertools", |
1597 | "once_cell", | 1620 | "once_cell", |
1598 | "parser", | 1621 | "parser", |
1599 | "profile", | 1622 | "profile", |
@@ -1625,7 +1648,6 @@ dependencies = [ | |||
1625 | "dissimilar", | 1648 | "dissimilar", |
1626 | "profile", | 1649 | "profile", |
1627 | "rustc-hash", | 1650 | "rustc-hash", |
1628 | "serde_json", | ||
1629 | "stdx", | 1651 | "stdx", |
1630 | "text-size", | 1652 | "text-size", |
1631 | ] | 1653 | ] |
@@ -1760,9 +1782,9 @@ dependencies = [ | |||
1760 | 1782 | ||
1761 | [[package]] | 1783 | [[package]] |
1762 | name = "tracing-tree" | 1784 | name = "tracing-tree" |
1763 | version = "0.1.8" | 1785 | version = "0.1.9" |
1764 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1765 | checksum = "1a60657cfbf397c603257a8230b3f427e6a2a4e5911a59331b9bb4dffff5b608" | 1787 | checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967" |
1766 | dependencies = [ | 1788 | dependencies = [ |
1767 | "ansi_term", | 1789 | "ansi_term", |
1768 | "atty", | 1790 | "atty", |
@@ -1922,19 +1944,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1922 | checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" | 1944 | checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" |
1923 | 1945 | ||
1924 | [[package]] | 1946 | [[package]] |
1947 | name = "xflags" | ||
1948 | version = "0.2.1" | ||
1949 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1950 | checksum = "59ad6ce6a0b7224130015b4ebac796478ac04e0079f5d222a690efea06a9208a" | ||
1951 | dependencies = [ | ||
1952 | "xflags-macros", | ||
1953 | ] | ||
1954 | |||
1955 | [[package]] | ||
1956 | name = "xflags-macros" | ||
1957 | version = "0.2.1" | ||
1958 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1959 | checksum = "c8037d3ca14996158b03c0fa905d0834906ef0fc7044df72c1f5ff690e5e62c9" | ||
1960 | dependencies = [ | ||
1961 | "proc-macro2", | ||
1962 | ] | ||
1963 | |||
1964 | [[package]] | ||
1925 | name = "xshell" | 1965 | name = "xshell" |
1926 | version = "0.1.8" | 1966 | version = "0.1.9" |
1927 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1967 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1928 | checksum = "ed373ede30cea03e8c0af22f48ee1ba80efbf06fec8b4746977e6ee703878de0" | 1968 | checksum = "6f18102278453c8f70ea5c514ac78cb4c73a0ef72a8273d17094b52f9584c0c1" |
1929 | dependencies = [ | 1969 | dependencies = [ |
1930 | "xshell-macros", | 1970 | "xshell-macros", |
1931 | ] | 1971 | ] |
1932 | 1972 | ||
1933 | [[package]] | 1973 | [[package]] |
1934 | name = "xshell-macros" | 1974 | name = "xshell-macros" |
1935 | version = "0.1.8" | 1975 | version = "0.1.9" |
1936 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1976 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1937 | checksum = "7f6af9f8119104697b0105989a73c578ce33f922d9d6f3dae0e8ae3d538db321" | 1977 | checksum = "6093c460064572007f885facc70bb0ca5e40a83ea7ff8b16c1abbee56fd2e767" |
1938 | 1978 | ||
1939 | [[package]] | 1979 | [[package]] |
1940 | name = "xtask" | 1980 | name = "xtask" |
@@ -1942,11 +1982,11 @@ version = "0.1.0" | |||
1942 | dependencies = [ | 1982 | dependencies = [ |
1943 | "anyhow", | 1983 | "anyhow", |
1944 | "flate2", | 1984 | "flate2", |
1945 | "pico-args", | ||
1946 | "proc-macro2", | 1985 | "proc-macro2", |
1947 | "quote", | 1986 | "quote", |
1948 | "ungrammar", | 1987 | "ungrammar", |
1949 | "walkdir", | 1988 | "walkdir", |
1950 | "write-json", | 1989 | "write-json", |
1990 | "xflags", | ||
1951 | "xshell", | 1991 | "xshell", |
1952 | ] | 1992 | ] |
@@ -42,6 +42,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 | |||
42 | * Website: https://rust-analyzer.github.io/ | 42 | * Website: https://rust-analyzer.github.io/ |
43 | * Metrics: https://rust-analyzer.github.io/metrics/ | 43 | * Metrics: https://rust-analyzer.github.io/metrics/ |
44 | * API docs: https://rust-analyzer.github.io/rust-analyzer/ide/ | 44 | * API docs: https://rust-analyzer.github.io/rust-analyzer/ide/ |
45 | * Changelog: https://rust-analyzer.github.io/thisweek | ||
45 | 46 | ||
46 | ## License | 47 | ## License |
47 | 48 | ||
diff --git a/crates/base_db/src/change.rs b/crates/base_db/src/change.rs index 043e03bba..04e294e41 100644 --- a/crates/base_db/src/change.rs +++ b/crates/base_db/src/change.rs | |||
@@ -19,7 +19,7 @@ pub struct Change { | |||
19 | 19 | ||
20 | impl fmt::Debug for Change { | 20 | impl fmt::Debug for Change { |
21 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 21 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
22 | let mut d = fmt.debug_struct("AnalysisChange"); | 22 | let mut d = fmt.debug_struct("Change"); |
23 | if let Some(roots) = &self.roots { | 23 | if let Some(roots) = &self.roots { |
24 | d.field("roots", roots); | 24 | d.field("roots", roots); |
25 | } | 25 | } |
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 deleted file mode 100644 index b3218833d..000000000 --- a/crates/hir/src/code_model.rs +++ /dev/null | |||
@@ -1,2128 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | use std::{iter, sync::Arc}; | ||
3 | |||
4 | use arrayvec::ArrayVec; | ||
5 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | ||
6 | use either::Either; | ||
7 | use hir_def::{ | ||
8 | adt::{ReprKind, StructKind, VariantData}, | ||
9 | expr::{BindingAnnotation, LabelId, Pat, PatId}, | ||
10 | import_map, | ||
11 | item_tree::ItemTreeNode, | ||
12 | lang_item::LangItemTarget, | ||
13 | path::ModPath, | ||
14 | per_ns::PerNs, | ||
15 | resolver::{HasResolver, Resolver}, | ||
16 | src::HasSource as _, | ||
17 | type_ref::{Mutability, TypeRef}, | ||
18 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | ||
19 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | ||
20 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | ||
21 | TypeParamId, UnionId, | ||
22 | }; | ||
23 | use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; | ||
24 | use hir_expand::{ | ||
25 | diagnostics::DiagnosticSink, | ||
26 | name::{name, AsName}, | ||
27 | MacroDefId, MacroDefKind, | ||
28 | }; | ||
29 | use hir_ty::{ | ||
30 | autoderef, | ||
31 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, | ||
32 | method_resolution, | ||
33 | traits::{FnTrait, Solution, SolutionVariables}, | ||
34 | ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, | ||
35 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty, | ||
36 | TyDefId, TyKind, TypeCtor, | ||
37 | }; | ||
38 | use rustc_hash::FxHashSet; | ||
39 | use stdx::{format_to, impl_from}; | ||
40 | use syntax::{ | ||
41 | ast::{self, AttrsOwner, NameOwner}, | ||
42 | AstNode, SmolStr, | ||
43 | }; | ||
44 | use tt::{Ident, Leaf, Literal, TokenTree}; | ||
45 | |||
46 | use crate::{ | ||
47 | db::{DefDatabase, HirDatabase}, | ||
48 | has_source::HasSource, | ||
49 | HirDisplay, InFile, Name, | ||
50 | }; | ||
51 | |||
52 | /// hir::Crate describes a single crate. It's the main interface with which | ||
53 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the | ||
54 | /// root module. | ||
55 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
56 | pub struct Crate { | ||
57 | pub(crate) id: CrateId, | ||
58 | } | ||
59 | |||
60 | #[derive(Debug)] | ||
61 | pub struct CrateDependency { | ||
62 | pub krate: Crate, | ||
63 | pub name: Name, | ||
64 | } | ||
65 | |||
66 | impl Crate { | ||
67 | pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> { | ||
68 | db.crate_graph()[self.id] | ||
69 | .dependencies | ||
70 | .iter() | ||
71 | .map(|dep| { | ||
72 | let krate = Crate { id: dep.crate_id }; | ||
73 | let name = dep.as_name(); | ||
74 | CrateDependency { krate, name } | ||
75 | }) | ||
76 | .collect() | ||
77 | } | ||
78 | |||
79 | // FIXME: add `transitive_reverse_dependencies`. | ||
80 | pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { | ||
81 | let crate_graph = db.crate_graph(); | ||
82 | crate_graph | ||
83 | .iter() | ||
84 | .filter(|&krate| { | ||
85 | crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id) | ||
86 | }) | ||
87 | .map(|id| Crate { id }) | ||
88 | .collect() | ||
89 | } | ||
90 | |||
91 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { | ||
92 | let def_map = db.crate_def_map(self.id); | ||
93 | Module { id: def_map.module_id(def_map.root()) } | ||
94 | } | ||
95 | |||
96 | pub fn root_file(self, db: &dyn HirDatabase) -> FileId { | ||
97 | db.crate_graph()[self.id].root_file_id | ||
98 | } | ||
99 | |||
100 | pub fn edition(self, db: &dyn HirDatabase) -> Edition { | ||
101 | db.crate_graph()[self.id].edition | ||
102 | } | ||
103 | |||
104 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> { | ||
105 | db.crate_graph()[self.id].display_name.clone() | ||
106 | } | ||
107 | |||
108 | pub fn query_external_importables( | ||
109 | self, | ||
110 | db: &dyn DefDatabase, | ||
111 | query: import_map::Query, | ||
112 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | ||
113 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { | ||
114 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | ||
115 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | ||
116 | }) | ||
117 | } | ||
118 | |||
119 | pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { | ||
120 | db.crate_graph().iter().map(|id| Crate { id }).collect() | ||
121 | } | ||
122 | |||
123 | /// Try to get the root URL of the documentation of a crate. | ||
124 | pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> { | ||
125 | // Look for #![doc(html_root_url = "...")] | ||
126 | let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into())); | ||
127 | let doc_attr_q = attrs.by_key("doc"); | ||
128 | |||
129 | if !doc_attr_q.exists() { | ||
130 | return None; | ||
131 | } | ||
132 | |||
133 | let doc_url = doc_attr_q.tt_values().map(|tt| { | ||
134 | let name = tt.token_trees.iter() | ||
135 | .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url")) | ||
136 | .skip(2) | ||
137 | .next(); | ||
138 | |||
139 | match name { | ||
140 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), | ||
141 | _ => None | ||
142 | } | ||
143 | }).flat_map(|t| t).next(); | ||
144 | |||
145 | doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") | ||
146 | } | ||
147 | } | ||
148 | |||
149 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
150 | pub struct Module { | ||
151 | pub(crate) id: ModuleId, | ||
152 | } | ||
153 | |||
154 | /// The defs which can be visible in the module. | ||
155 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
156 | pub enum ModuleDef { | ||
157 | Module(Module), | ||
158 | Function(Function), | ||
159 | Adt(Adt), | ||
160 | // Can't be directly declared, but can be imported. | ||
161 | Variant(Variant), | ||
162 | Const(Const), | ||
163 | Static(Static), | ||
164 | Trait(Trait), | ||
165 | TypeAlias(TypeAlias), | ||
166 | BuiltinType(BuiltinType), | ||
167 | } | ||
168 | impl_from!( | ||
169 | Module, | ||
170 | Function, | ||
171 | Adt(Struct, Enum, Union), | ||
172 | Variant, | ||
173 | Const, | ||
174 | Static, | ||
175 | Trait, | ||
176 | TypeAlias, | ||
177 | BuiltinType | ||
178 | for ModuleDef | ||
179 | ); | ||
180 | |||
181 | impl From<VariantDef> for ModuleDef { | ||
182 | fn from(var: VariantDef) -> Self { | ||
183 | match var { | ||
184 | VariantDef::Struct(t) => Adt::from(t).into(), | ||
185 | VariantDef::Union(t) => Adt::from(t).into(), | ||
186 | VariantDef::Variant(t) => t.into(), | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | impl ModuleDef { | ||
192 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | ||
193 | match self { | ||
194 | ModuleDef::Module(it) => it.parent(db), | ||
195 | ModuleDef::Function(it) => Some(it.module(db)), | ||
196 | ModuleDef::Adt(it) => Some(it.module(db)), | ||
197 | ModuleDef::Variant(it) => Some(it.module(db)), | ||
198 | ModuleDef::Const(it) => Some(it.module(db)), | ||
199 | ModuleDef::Static(it) => Some(it.module(db)), | ||
200 | ModuleDef::Trait(it) => Some(it.module(db)), | ||
201 | ModuleDef::TypeAlias(it) => Some(it.module(db)), | ||
202 | ModuleDef::BuiltinType(_) => None, | ||
203 | } | ||
204 | } | ||
205 | |||
206 | pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> { | ||
207 | let mut segments = Vec::new(); | ||
208 | segments.push(self.name(db)?.to_string()); | ||
209 | for m in self.module(db)?.path_to_root(db) { | ||
210 | segments.extend(m.name(db).map(|it| it.to_string())) | ||
211 | } | ||
212 | segments.reverse(); | ||
213 | Some(segments.join("::")) | ||
214 | } | ||
215 | |||
216 | pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> { | ||
217 | let module = match self { | ||
218 | ModuleDef::Module(it) => it.parent(db)?, | ||
219 | ModuleDef::Function(it) => return Some(it.visibility(db)), | ||
220 | ModuleDef::Adt(it) => it.module(db), | ||
221 | ModuleDef::Variant(it) => { | ||
222 | let parent = it.parent_enum(db); | ||
223 | let module = it.module(db); | ||
224 | return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent))); | ||
225 | } | ||
226 | ModuleDef::Const(it) => return Some(it.visibility(db)), | ||
227 | ModuleDef::Static(it) => it.module(db), | ||
228 | ModuleDef::Trait(it) => it.module(db), | ||
229 | ModuleDef::TypeAlias(it) => return Some(it.visibility(db)), | ||
230 | ModuleDef::BuiltinType(_) => return None, | ||
231 | }; | ||
232 | |||
233 | module.visibility_of(db, self) | ||
234 | } | ||
235 | |||
236 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
237 | match self { | ||
238 | ModuleDef::Adt(it) => Some(it.name(db)), | ||
239 | ModuleDef::Trait(it) => Some(it.name(db)), | ||
240 | ModuleDef::Function(it) => Some(it.name(db)), | ||
241 | ModuleDef::Variant(it) => Some(it.name(db)), | ||
242 | ModuleDef::TypeAlias(it) => Some(it.name(db)), | ||
243 | ModuleDef::Module(it) => it.name(db), | ||
244 | ModuleDef::Const(it) => it.name(db), | ||
245 | ModuleDef::Static(it) => it.name(db), | ||
246 | |||
247 | ModuleDef::BuiltinType(it) => Some(it.name()), | ||
248 | } | ||
249 | } | ||
250 | |||
251 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | ||
252 | let id = match self { | ||
253 | ModuleDef::Adt(it) => match it { | ||
254 | Adt::Struct(it) => it.id.into(), | ||
255 | Adt::Enum(it) => it.id.into(), | ||
256 | Adt::Union(it) => it.id.into(), | ||
257 | }, | ||
258 | ModuleDef::Trait(it) => it.id.into(), | ||
259 | ModuleDef::Function(it) => it.id.into(), | ||
260 | ModuleDef::TypeAlias(it) => it.id.into(), | ||
261 | ModuleDef::Module(it) => it.id.into(), | ||
262 | ModuleDef::Const(it) => it.id.into(), | ||
263 | ModuleDef::Static(it) => it.id.into(), | ||
264 | _ => return, | ||
265 | }; | ||
266 | |||
267 | let module = match self.module(db) { | ||
268 | Some(it) => it, | ||
269 | None => return, | ||
270 | }; | ||
271 | |||
272 | hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink) | ||
273 | } | ||
274 | } | ||
275 | |||
276 | impl Module { | ||
277 | /// Name of this module. | ||
278 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
279 | let def_map = self.id.def_map(db.upcast()); | ||
280 | let parent = def_map[self.id.local_id].parent?; | ||
281 | def_map[parent].children.iter().find_map(|(name, module_id)| { | ||
282 | if *module_id == self.id.local_id { | ||
283 | Some(name.clone()) | ||
284 | } else { | ||
285 | None | ||
286 | } | ||
287 | }) | ||
288 | } | ||
289 | |||
290 | /// Returns the crate this module is part of. | ||
291 | pub fn krate(self) -> Crate { | ||
292 | Crate { id: self.id.krate() } | ||
293 | } | ||
294 | |||
295 | /// Topmost parent of this module. Every module has a `crate_root`, but some | ||
296 | /// might be missing `krate`. This can happen if a module's file is not included | ||
297 | /// in the module tree of any target in `Cargo.toml`. | ||
298 | pub fn crate_root(self, db: &dyn HirDatabase) -> Module { | ||
299 | let def_map = db.crate_def_map(self.id.krate()); | ||
300 | Module { id: def_map.module_id(def_map.root()) } | ||
301 | } | ||
302 | |||
303 | /// Iterates over all child modules. | ||
304 | pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> { | ||
305 | let def_map = self.id.def_map(db.upcast()); | ||
306 | let children = def_map[self.id.local_id] | ||
307 | .children | ||
308 | .iter() | ||
309 | .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) }) | ||
310 | .collect::<Vec<_>>(); | ||
311 | children.into_iter() | ||
312 | } | ||
313 | |||
314 | /// Finds a parent module. | ||
315 | pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> { | ||
316 | // FIXME: handle block expressions as modules (their parent is in a different DefMap) | ||
317 | let def_map = self.id.def_map(db.upcast()); | ||
318 | let parent_id = def_map[self.id.local_id].parent?; | ||
319 | Some(Module { id: def_map.module_id(parent_id) }) | ||
320 | } | ||
321 | |||
322 | pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> { | ||
323 | let mut res = vec![self]; | ||
324 | let mut curr = self; | ||
325 | while let Some(next) = curr.parent(db) { | ||
326 | res.push(next); | ||
327 | curr = next | ||
328 | } | ||
329 | res | ||
330 | } | ||
331 | |||
332 | /// Returns a `ModuleScope`: a set of items, visible in this module. | ||
333 | pub fn scope( | ||
334 | self, | ||
335 | db: &dyn HirDatabase, | ||
336 | visible_from: Option<Module>, | ||
337 | ) -> Vec<(Name, ScopeDef)> { | ||
338 | self.id.def_map(db.upcast())[self.id.local_id] | ||
339 | .scope | ||
340 | .entries() | ||
341 | .filter_map(|(name, def)| { | ||
342 | if let Some(m) = visible_from { | ||
343 | let filtered = | ||
344 | def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id)); | ||
345 | if filtered.is_none() && !def.is_none() { | ||
346 | None | ||
347 | } else { | ||
348 | Some((name, filtered)) | ||
349 | } | ||
350 | } else { | ||
351 | Some((name, def)) | ||
352 | } | ||
353 | }) | ||
354 | .flat_map(|(name, def)| { | ||
355 | ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item)) | ||
356 | }) | ||
357 | .collect() | ||
358 | } | ||
359 | |||
360 | pub fn visibility_of(self, db: &dyn HirDatabase, def: &ModuleDef) -> Option<Visibility> { | ||
361 | self.id.def_map(db.upcast())[self.id.local_id].scope.visibility_of(def.clone().into()) | ||
362 | } | ||
363 | |||
364 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | ||
365 | let _p = profile::span("Module::diagnostics").detail(|| { | ||
366 | format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) | ||
367 | }); | ||
368 | let crate_def_map = self.id.def_map(db.upcast()); | ||
369 | crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink); | ||
370 | for decl in self.declarations(db) { | ||
371 | match decl { | ||
372 | crate::ModuleDef::Function(f) => f.diagnostics(db, sink), | ||
373 | crate::ModuleDef::Module(m) => { | ||
374 | // Only add diagnostics from inline modules | ||
375 | if crate_def_map[m.id.local_id].origin.is_inline() { | ||
376 | m.diagnostics(db, sink) | ||
377 | } | ||
378 | } | ||
379 | _ => { | ||
380 | decl.diagnostics(db, sink); | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | |||
385 | for impl_def in self.impl_defs(db) { | ||
386 | for item in impl_def.items(db) { | ||
387 | if let AssocItem::Function(f) = item { | ||
388 | f.diagnostics(db, sink); | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | |||
394 | pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> { | ||
395 | let def_map = self.id.def_map(db.upcast()); | ||
396 | def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect() | ||
397 | } | ||
398 | |||
399 | pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> { | ||
400 | let def_map = self.id.def_map(db.upcast()); | ||
401 | def_map[self.id.local_id].scope.impls().map(Impl::from).collect() | ||
402 | } | ||
403 | |||
404 | /// Finds a path that can be used to refer to the given item from within | ||
405 | /// this module, if possible. | ||
406 | pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> { | ||
407 | hir_def::find_path::find_path(db, item.into(), self.into()) | ||
408 | } | ||
409 | |||
410 | /// Finds a path that can be used to refer to the given item from within | ||
411 | /// this module, if possible. This is used for returning import paths for use-statements. | ||
412 | pub fn find_use_path_prefixed( | ||
413 | self, | ||
414 | db: &dyn DefDatabase, | ||
415 | item: impl Into<ItemInNs>, | ||
416 | prefix_kind: PrefixKind, | ||
417 | ) -> Option<ModPath> { | ||
418 | hir_def::find_path::find_path_prefixed(db, item.into(), self.into(), prefix_kind) | ||
419 | } | ||
420 | } | ||
421 | |||
422 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
423 | pub struct Field { | ||
424 | pub(crate) parent: VariantDef, | ||
425 | pub(crate) id: LocalFieldId, | ||
426 | } | ||
427 | |||
428 | #[derive(Debug, PartialEq, Eq)] | ||
429 | pub enum FieldSource { | ||
430 | Named(ast::RecordField), | ||
431 | Pos(ast::TupleField), | ||
432 | } | ||
433 | |||
434 | impl Field { | ||
435 | pub fn name(&self, db: &dyn HirDatabase) -> Name { | ||
436 | self.parent.variant_data(db).fields()[self.id].name.clone() | ||
437 | } | ||
438 | |||
439 | /// Returns the type as in the signature of the struct (i.e., with | ||
440 | /// placeholder types for type parameters). This is good for showing | ||
441 | /// signature help, but not so good to actually get the type of the field | ||
442 | /// when you actually have a variable of the struct. | ||
443 | pub fn signature_ty(&self, db: &dyn HirDatabase) -> Type { | ||
444 | let var_id = self.parent.into(); | ||
445 | let generic_def_id: GenericDefId = match self.parent { | ||
446 | VariantDef::Struct(it) => it.id.into(), | ||
447 | VariantDef::Union(it) => it.id.into(), | ||
448 | VariantDef::Variant(it) => it.parent.id.into(), | ||
449 | }; | ||
450 | let substs = Substs::type_params(db, generic_def_id); | ||
451 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); | ||
452 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) | ||
453 | } | ||
454 | |||
455 | pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef { | ||
456 | self.parent | ||
457 | } | ||
458 | } | ||
459 | |||
460 | impl HasVisibility for Field { | ||
461 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
462 | let variant_data = self.parent.variant_data(db); | ||
463 | let visibility = &variant_data.fields()[self.id].visibility; | ||
464 | let parent_id: hir_def::VariantId = self.parent.into(); | ||
465 | visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast())) | ||
466 | } | ||
467 | } | ||
468 | |||
469 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
470 | pub struct Struct { | ||
471 | pub(crate) id: StructId, | ||
472 | } | ||
473 | |||
474 | impl Struct { | ||
475 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
476 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | ||
477 | } | ||
478 | |||
479 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
480 | Some(self.module(db).krate()) | ||
481 | } | ||
482 | |||
483 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
484 | db.struct_data(self.id).name.clone() | ||
485 | } | ||
486 | |||
487 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | ||
488 | db.struct_data(self.id) | ||
489 | .variant_data | ||
490 | .fields() | ||
491 | .iter() | ||
492 | .map(|(id, _)| Field { parent: self.into(), id }) | ||
493 | .collect() | ||
494 | } | ||
495 | |||
496 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
497 | Type::from_def( | ||
498 | db, | ||
499 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
500 | self.id, | ||
501 | ) | ||
502 | } | ||
503 | |||
504 | pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { | ||
505 | db.struct_data(self.id).repr.clone() | ||
506 | } | ||
507 | |||
508 | pub fn kind(self, db: &dyn HirDatabase) -> StructKind { | ||
509 | self.variant_data(db).kind() | ||
510 | } | ||
511 | |||
512 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | ||
513 | db.struct_data(self.id).variant_data.clone() | ||
514 | } | ||
515 | } | ||
516 | |||
517 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
518 | pub struct Union { | ||
519 | pub(crate) id: UnionId, | ||
520 | } | ||
521 | |||
522 | impl Union { | ||
523 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
524 | db.union_data(self.id).name.clone() | ||
525 | } | ||
526 | |||
527 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
528 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | ||
529 | } | ||
530 | |||
531 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
532 | Type::from_def( | ||
533 | db, | ||
534 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
535 | self.id, | ||
536 | ) | ||
537 | } | ||
538 | |||
539 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | ||
540 | db.union_data(self.id) | ||
541 | .variant_data | ||
542 | .fields() | ||
543 | .iter() | ||
544 | .map(|(id, _)| Field { parent: self.into(), id }) | ||
545 | .collect() | ||
546 | } | ||
547 | |||
548 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | ||
549 | db.union_data(self.id).variant_data.clone() | ||
550 | } | ||
551 | } | ||
552 | |||
553 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
554 | pub struct Enum { | ||
555 | pub(crate) id: EnumId, | ||
556 | } | ||
557 | |||
558 | impl Enum { | ||
559 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
560 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | ||
561 | } | ||
562 | |||
563 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
564 | Some(self.module(db).krate()) | ||
565 | } | ||
566 | |||
567 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
568 | db.enum_data(self.id).name.clone() | ||
569 | } | ||
570 | |||
571 | pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> { | ||
572 | db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect() | ||
573 | } | ||
574 | |||
575 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
576 | Type::from_def( | ||
577 | db, | ||
578 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
579 | self.id, | ||
580 | ) | ||
581 | } | ||
582 | } | ||
583 | |||
584 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
585 | pub struct Variant { | ||
586 | pub(crate) parent: Enum, | ||
587 | pub(crate) id: LocalEnumVariantId, | ||
588 | } | ||
589 | |||
590 | impl Variant { | ||
591 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
592 | self.parent.module(db) | ||
593 | } | ||
594 | pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { | ||
595 | self.parent | ||
596 | } | ||
597 | |||
598 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
599 | db.enum_data(self.parent.id).variants[self.id].name.clone() | ||
600 | } | ||
601 | |||
602 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | ||
603 | self.variant_data(db) | ||
604 | .fields() | ||
605 | .iter() | ||
606 | .map(|(id, _)| Field { parent: self.into(), id }) | ||
607 | .collect() | ||
608 | } | ||
609 | |||
610 | pub fn kind(self, db: &dyn HirDatabase) -> StructKind { | ||
611 | self.variant_data(db).kind() | ||
612 | } | ||
613 | |||
614 | pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | ||
615 | db.enum_data(self.parent.id).variants[self.id].variant_data.clone() | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /// A Data Type | ||
620 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
621 | pub enum Adt { | ||
622 | Struct(Struct), | ||
623 | Union(Union), | ||
624 | Enum(Enum), | ||
625 | } | ||
626 | impl_from!(Struct, Union, Enum for Adt); | ||
627 | |||
628 | impl Adt { | ||
629 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | ||
630 | let subst = db.generic_defaults(self.into()); | ||
631 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) | ||
632 | } | ||
633 | |||
634 | /// Turns this ADT into a type. Any type parameters of the ADT will be | ||
635 | /// turned into unknown types, which is good for e.g. finding the most | ||
636 | /// general set of completions, but will not look very nice when printed. | ||
637 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
638 | let id = AdtId::from(self); | ||
639 | Type::from_def(db, id.module(db.upcast()).krate(), id) | ||
640 | } | ||
641 | |||
642 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
643 | match self { | ||
644 | Adt::Struct(s) => s.module(db), | ||
645 | Adt::Union(s) => s.module(db), | ||
646 | Adt::Enum(e) => e.module(db), | ||
647 | } | ||
648 | } | ||
649 | |||
650 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
651 | Some(self.module(db).krate()) | ||
652 | } | ||
653 | |||
654 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
655 | match self { | ||
656 | Adt::Struct(s) => s.name(db), | ||
657 | Adt::Union(u) => u.name(db), | ||
658 | Adt::Enum(e) => e.name(db), | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | |||
663 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
664 | pub enum VariantDef { | ||
665 | Struct(Struct), | ||
666 | Union(Union), | ||
667 | Variant(Variant), | ||
668 | } | ||
669 | impl_from!(Struct, Union, Variant for VariantDef); | ||
670 | |||
671 | impl VariantDef { | ||
672 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | ||
673 | match self { | ||
674 | VariantDef::Struct(it) => it.fields(db), | ||
675 | VariantDef::Union(it) => it.fields(db), | ||
676 | VariantDef::Variant(it) => it.fields(db), | ||
677 | } | ||
678 | } | ||
679 | |||
680 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
681 | match self { | ||
682 | VariantDef::Struct(it) => it.module(db), | ||
683 | VariantDef::Union(it) => it.module(db), | ||
684 | VariantDef::Variant(it) => it.module(db), | ||
685 | } | ||
686 | } | ||
687 | |||
688 | pub fn name(&self, db: &dyn HirDatabase) -> Name { | ||
689 | match self { | ||
690 | VariantDef::Struct(s) => s.name(db), | ||
691 | VariantDef::Union(u) => u.name(db), | ||
692 | VariantDef::Variant(e) => e.name(db), | ||
693 | } | ||
694 | } | ||
695 | |||
696 | pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | ||
697 | match self { | ||
698 | VariantDef::Struct(it) => it.variant_data(db), | ||
699 | VariantDef::Union(it) => it.variant_data(db), | ||
700 | VariantDef::Variant(it) => it.variant_data(db), | ||
701 | } | ||
702 | } | ||
703 | } | ||
704 | |||
705 | /// The defs which have a body. | ||
706 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
707 | pub enum DefWithBody { | ||
708 | Function(Function), | ||
709 | Static(Static), | ||
710 | Const(Const), | ||
711 | } | ||
712 | impl_from!(Function, Const, Static for DefWithBody); | ||
713 | |||
714 | impl DefWithBody { | ||
715 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
716 | match self { | ||
717 | DefWithBody::Const(c) => c.module(db), | ||
718 | DefWithBody::Function(f) => f.module(db), | ||
719 | DefWithBody::Static(s) => s.module(db), | ||
720 | } | ||
721 | } | ||
722 | |||
723 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
724 | match self { | ||
725 | DefWithBody::Function(f) => Some(f.name(db)), | ||
726 | DefWithBody::Static(s) => s.name(db), | ||
727 | DefWithBody::Const(c) => c.name(db), | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | |||
732 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
733 | pub struct Function { | ||
734 | pub(crate) id: FunctionId, | ||
735 | } | ||
736 | |||
737 | impl Function { | ||
738 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
739 | self.id.lookup(db.upcast()).module(db.upcast()).into() | ||
740 | } | ||
741 | |||
742 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
743 | Some(self.module(db).krate()) | ||
744 | } | ||
745 | |||
746 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
747 | db.function_data(self.id).name.clone() | ||
748 | } | ||
749 | |||
750 | /// Get this function's return type | ||
751 | pub fn ret_type(self, db: &dyn HirDatabase) -> Type { | ||
752 | let resolver = self.id.resolver(db.upcast()); | ||
753 | let ret_type = &db.function_data(self.id).ret_type; | ||
754 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | ||
755 | let environment = TraitEnvironment::lower(db, &resolver); | ||
756 | Type { | ||
757 | krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
758 | ty: InEnvironment { value: Ty::from_hir_ext(&ctx, ret_type).0, environment }, | ||
759 | } | ||
760 | } | ||
761 | |||
762 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { | ||
763 | if !db.function_data(self.id).has_self_param { | ||
764 | return None; | ||
765 | } | ||
766 | Some(SelfParam { func: self.id }) | ||
767 | } | ||
768 | |||
769 | pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> { | ||
770 | let resolver = self.id.resolver(db.upcast()); | ||
771 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | ||
772 | let environment = TraitEnvironment::lower(db, &resolver); | ||
773 | db.function_data(self.id) | ||
774 | .params | ||
775 | .iter() | ||
776 | .map(|type_ref| { | ||
777 | let ty = Type { | ||
778 | krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
779 | ty: InEnvironment { | ||
780 | value: Ty::from_hir_ext(&ctx, type_ref).0, | ||
781 | environment: environment.clone(), | ||
782 | }, | ||
783 | }; | ||
784 | Param { ty } | ||
785 | }) | ||
786 | .collect() | ||
787 | } | ||
788 | pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> { | ||
789 | if self.self_param(db).is_none() { | ||
790 | return None; | ||
791 | } | ||
792 | let mut res = self.assoc_fn_params(db); | ||
793 | res.remove(0); | ||
794 | Some(res) | ||
795 | } | ||
796 | |||
797 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | ||
798 | db.function_data(self.id).is_unsafe | ||
799 | } | ||
800 | |||
801 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | ||
802 | let krate = self.module(db).id.krate(); | ||
803 | hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); | ||
804 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | ||
805 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | ||
806 | } | ||
807 | |||
808 | /// Whether this function declaration has a definition. | ||
809 | /// | ||
810 | /// This is false in the case of required (not provided) trait methods. | ||
811 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | ||
812 | db.function_data(self.id).has_body | ||
813 | } | ||
814 | |||
815 | /// A textual representation of the HIR of this function for debugging purposes. | ||
816 | pub fn debug_hir(self, db: &dyn HirDatabase) -> String { | ||
817 | let body = db.body(self.id.into()); | ||
818 | |||
819 | let mut result = String::new(); | ||
820 | format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db)); | ||
821 | for (id, expr) in body.exprs.iter() { | ||
822 | format_to!(result, "{:?}: {:?}\n", id, expr); | ||
823 | } | ||
824 | |||
825 | result | ||
826 | } | ||
827 | } | ||
828 | |||
829 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. | ||
830 | pub enum Access { | ||
831 | Shared, | ||
832 | Exclusive, | ||
833 | Owned, | ||
834 | } | ||
835 | |||
836 | impl From<Mutability> for Access { | ||
837 | fn from(mutability: Mutability) -> Access { | ||
838 | match mutability { | ||
839 | Mutability::Shared => Access::Shared, | ||
840 | Mutability::Mut => Access::Exclusive, | ||
841 | } | ||
842 | } | ||
843 | } | ||
844 | |||
845 | #[derive(Debug)] | ||
846 | pub struct Param { | ||
847 | ty: Type, | ||
848 | } | ||
849 | |||
850 | impl Param { | ||
851 | pub fn ty(&self) -> &Type { | ||
852 | &self.ty | ||
853 | } | ||
854 | } | ||
855 | |||
856 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
857 | pub struct SelfParam { | ||
858 | func: FunctionId, | ||
859 | } | ||
860 | |||
861 | impl SelfParam { | ||
862 | pub fn access(self, db: &dyn HirDatabase) -> Access { | ||
863 | let func_data = db.function_data(self.func); | ||
864 | func_data | ||
865 | .params | ||
866 | .first() | ||
867 | .map(|param| match *param { | ||
868 | TypeRef::Reference(.., mutability) => mutability.into(), | ||
869 | _ => Access::Owned, | ||
870 | }) | ||
871 | .unwrap_or(Access::Owned) | ||
872 | } | ||
873 | } | ||
874 | |||
875 | impl HasVisibility for Function { | ||
876 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
877 | let function_data = db.function_data(self.id); | ||
878 | let visibility = &function_data.visibility; | ||
879 | visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
880 | } | ||
881 | } | ||
882 | |||
883 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
884 | pub struct Const { | ||
885 | pub(crate) id: ConstId, | ||
886 | } | ||
887 | |||
888 | impl Const { | ||
889 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
890 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | ||
891 | } | ||
892 | |||
893 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
894 | Some(self.module(db).krate()) | ||
895 | } | ||
896 | |||
897 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
898 | db.const_data(self.id).name.clone() | ||
899 | } | ||
900 | } | ||
901 | |||
902 | impl HasVisibility for Const { | ||
903 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
904 | let function_data = db.const_data(self.id); | ||
905 | let visibility = &function_data.visibility; | ||
906 | visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
907 | } | ||
908 | } | ||
909 | |||
910 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
911 | pub struct Static { | ||
912 | pub(crate) id: StaticId, | ||
913 | } | ||
914 | |||
915 | impl Static { | ||
916 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
917 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | ||
918 | } | ||
919 | |||
920 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
921 | Some(self.module(db).krate()) | ||
922 | } | ||
923 | |||
924 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
925 | db.static_data(self.id).name.clone() | ||
926 | } | ||
927 | |||
928 | pub fn is_mut(self, db: &dyn HirDatabase) -> bool { | ||
929 | db.static_data(self.id).mutable | ||
930 | } | ||
931 | } | ||
932 | |||
933 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
934 | pub struct Trait { | ||
935 | pub(crate) id: TraitId, | ||
936 | } | ||
937 | |||
938 | impl Trait { | ||
939 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
940 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | ||
941 | } | ||
942 | |||
943 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
944 | db.trait_data(self.id).name.clone() | ||
945 | } | ||
946 | |||
947 | pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> { | ||
948 | db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() | ||
949 | } | ||
950 | |||
951 | pub fn is_auto(self, db: &dyn HirDatabase) -> bool { | ||
952 | db.trait_data(self.id).auto | ||
953 | } | ||
954 | } | ||
955 | |||
956 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
957 | pub struct TypeAlias { | ||
958 | pub(crate) id: TypeAliasId, | ||
959 | } | ||
960 | |||
961 | impl TypeAlias { | ||
962 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | ||
963 | let subst = db.generic_defaults(self.id.into()); | ||
964 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) | ||
965 | } | ||
966 | |||
967 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
968 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | ||
969 | } | ||
970 | |||
971 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
972 | Some(self.module(db).krate()) | ||
973 | } | ||
974 | |||
975 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | ||
976 | db.type_alias_data(self.id).type_ref.clone() | ||
977 | } | ||
978 | |||
979 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
980 | Type::from_def(db, self.id.lookup(db.upcast()).module(db.upcast()).krate(), self.id) | ||
981 | } | ||
982 | |||
983 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
984 | db.type_alias_data(self.id).name.clone() | ||
985 | } | ||
986 | } | ||
987 | |||
988 | impl HasVisibility for TypeAlias { | ||
989 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
990 | let function_data = db.type_alias_data(self.id); | ||
991 | let visibility = &function_data.visibility; | ||
992 | visibility.resolve(db.upcast(), &self.id.resolver(db.upcast())) | ||
993 | } | ||
994 | } | ||
995 | |||
996 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
997 | pub struct BuiltinType { | ||
998 | pub(crate) inner: hir_def::builtin_type::BuiltinType, | ||
999 | } | ||
1000 | |||
1001 | impl BuiltinType { | ||
1002 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { | ||
1003 | let resolver = module.id.resolver(db.upcast()); | ||
1004 | Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) | ||
1005 | .expect("crate not present in resolver") | ||
1006 | } | ||
1007 | |||
1008 | pub fn name(self) -> Name { | ||
1009 | self.inner.as_name() | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
1014 | pub struct MacroDef { | ||
1015 | pub(crate) id: MacroDefId, | ||
1016 | } | ||
1017 | |||
1018 | impl MacroDef { | ||
1019 | /// FIXME: right now, this just returns the root module of the crate that | ||
1020 | /// defines this macro. The reasons for this is that macros are expanded | ||
1021 | /// early, in `hir_expand`, where modules simply do not exist yet. | ||
1022 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | ||
1023 | let krate = self.id.krate; | ||
1024 | let def_map = db.crate_def_map(krate); | ||
1025 | let module_id = def_map.root(); | ||
1026 | Some(Module { id: def_map.module_id(module_id) }) | ||
1027 | } | ||
1028 | |||
1029 | /// XXX: this parses the file | ||
1030 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
1031 | self.source(db)?.value.name().map(|it| it.as_name()) | ||
1032 | } | ||
1033 | |||
1034 | /// Indicate it is a proc-macro | ||
1035 | pub fn is_proc_macro(&self) -> bool { | ||
1036 | matches!(self.id.kind, MacroDefKind::ProcMacro(_)) | ||
1037 | } | ||
1038 | |||
1039 | /// Indicate it is a derive macro | ||
1040 | pub fn is_derive_macro(&self) -> bool { | ||
1041 | matches!(self.id.kind, MacroDefKind::ProcMacro(_) | MacroDefKind::BuiltInDerive(_)) | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | /// Invariant: `inner.as_assoc_item(db).is_some()` | ||
1046 | /// We do not actively enforce this invariant. | ||
1047 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
1048 | pub enum AssocItem { | ||
1049 | Function(Function), | ||
1050 | Const(Const), | ||
1051 | TypeAlias(TypeAlias), | ||
1052 | } | ||
1053 | pub enum AssocItemContainer { | ||
1054 | Trait(Trait), | ||
1055 | Impl(Impl), | ||
1056 | } | ||
1057 | pub trait AsAssocItem { | ||
1058 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>; | ||
1059 | } | ||
1060 | |||
1061 | impl AsAssocItem for Function { | ||
1062 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { | ||
1063 | as_assoc_item(db, AssocItem::Function, self.id) | ||
1064 | } | ||
1065 | } | ||
1066 | impl AsAssocItem for Const { | ||
1067 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { | ||
1068 | as_assoc_item(db, AssocItem::Const, self.id) | ||
1069 | } | ||
1070 | } | ||
1071 | impl AsAssocItem for TypeAlias { | ||
1072 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { | ||
1073 | as_assoc_item(db, AssocItem::TypeAlias, self.id) | ||
1074 | } | ||
1075 | } | ||
1076 | impl AsAssocItem for ModuleDef { | ||
1077 | fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { | ||
1078 | match self { | ||
1079 | ModuleDef::Function(it) => it.as_assoc_item(db), | ||
1080 | ModuleDef::Const(it) => it.as_assoc_item(db), | ||
1081 | ModuleDef::TypeAlias(it) => it.as_assoc_item(db), | ||
1082 | _ => None, | ||
1083 | } | ||
1084 | } | ||
1085 | } | ||
1086 | fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem> | ||
1087 | where | ||
1088 | ID: Lookup<Data = AssocItemLoc<AST>>, | ||
1089 | DEF: From<ID>, | ||
1090 | CTOR: FnOnce(DEF) -> AssocItem, | ||
1091 | AST: ItemTreeNode, | ||
1092 | { | ||
1093 | match id.lookup(db.upcast()).container { | ||
1094 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | ||
1095 | AssocContainerId::ContainerId(_) => None, | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | impl AssocItem { | ||
1100 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
1101 | match self { | ||
1102 | AssocItem::Function(it) => Some(it.name(db)), | ||
1103 | AssocItem::Const(it) => it.name(db), | ||
1104 | AssocItem::TypeAlias(it) => Some(it.name(db)), | ||
1105 | } | ||
1106 | } | ||
1107 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1108 | match self { | ||
1109 | AssocItem::Function(f) => f.module(db), | ||
1110 | AssocItem::Const(c) => c.module(db), | ||
1111 | AssocItem::TypeAlias(t) => t.module(db), | ||
1112 | } | ||
1113 | } | ||
1114 | pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer { | ||
1115 | let container = match self { | ||
1116 | AssocItem::Function(it) => it.id.lookup(db.upcast()).container, | ||
1117 | AssocItem::Const(it) => it.id.lookup(db.upcast()).container, | ||
1118 | AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container, | ||
1119 | }; | ||
1120 | match container { | ||
1121 | AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), | ||
1122 | AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()), | ||
1123 | AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1128 | match self.container(db) { | ||
1129 | AssocItemContainer::Trait(t) => Some(t), | ||
1130 | _ => None, | ||
1131 | } | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | impl HasVisibility for AssocItem { | ||
1136 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||
1137 | match self { | ||
1138 | AssocItem::Function(f) => f.visibility(db), | ||
1139 | AssocItem::Const(c) => c.visibility(db), | ||
1140 | AssocItem::TypeAlias(t) => t.visibility(db), | ||
1141 | } | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
1146 | pub enum GenericDef { | ||
1147 | Function(Function), | ||
1148 | Adt(Adt), | ||
1149 | Trait(Trait), | ||
1150 | TypeAlias(TypeAlias), | ||
1151 | Impl(Impl), | ||
1152 | // enum variants cannot have generics themselves, but their parent enums | ||
1153 | // can, and this makes some code easier to write | ||
1154 | Variant(Variant), | ||
1155 | // consts can have type parameters from their parents (i.e. associated consts of traits) | ||
1156 | Const(Const), | ||
1157 | } | ||
1158 | impl_from!( | ||
1159 | Function, | ||
1160 | Adt(Struct, Enum, Union), | ||
1161 | Trait, | ||
1162 | TypeAlias, | ||
1163 | Impl, | ||
1164 | Variant, | ||
1165 | Const | ||
1166 | for GenericDef | ||
1167 | ); | ||
1168 | |||
1169 | impl GenericDef { | ||
1170 | pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> { | ||
1171 | let generics = db.generic_params(self.into()); | ||
1172 | let ty_params = generics | ||
1173 | .types | ||
1174 | .iter() | ||
1175 | .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) | ||
1176 | .map(GenericParam::TypeParam); | ||
1177 | let lt_params = generics | ||
1178 | .lifetimes | ||
1179 | .iter() | ||
1180 | .map(|(local_id, _)| LifetimeParam { | ||
1181 | id: LifetimeParamId { parent: self.into(), local_id }, | ||
1182 | }) | ||
1183 | .map(GenericParam::LifetimeParam); | ||
1184 | let const_params = generics | ||
1185 | .consts | ||
1186 | .iter() | ||
1187 | .map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } }) | ||
1188 | .map(GenericParam::ConstParam); | ||
1189 | ty_params.chain(lt_params).chain(const_params).collect() | ||
1190 | } | ||
1191 | |||
1192 | pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { | ||
1193 | let generics = db.generic_params(self.into()); | ||
1194 | generics | ||
1195 | .types | ||
1196 | .iter() | ||
1197 | .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) | ||
1198 | .collect() | ||
1199 | } | ||
1200 | } | ||
1201 | |||
1202 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1203 | pub struct Local { | ||
1204 | pub(crate) parent: DefWithBodyId, | ||
1205 | pub(crate) pat_id: PatId, | ||
1206 | } | ||
1207 | |||
1208 | impl Local { | ||
1209 | pub fn is_param(self, db: &dyn HirDatabase) -> bool { | ||
1210 | let src = self.source(db); | ||
1211 | match src.value { | ||
1212 | Either::Left(bind_pat) => { | ||
1213 | bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind())) | ||
1214 | } | ||
1215 | Either::Right(_self_param) => true, | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | // FIXME: why is this an option? It shouldn't be? | ||
1220 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
1221 | let body = db.body(self.parent.into()); | ||
1222 | match &body[self.pat_id] { | ||
1223 | Pat::Bind { name, .. } => Some(name.clone()), | ||
1224 | _ => None, | ||
1225 | } | ||
1226 | } | ||
1227 | |||
1228 | pub fn is_self(self, db: &dyn HirDatabase) -> bool { | ||
1229 | self.name(db) == Some(name![self]) | ||
1230 | } | ||
1231 | |||
1232 | pub fn is_mut(self, db: &dyn HirDatabase) -> bool { | ||
1233 | let body = db.body(self.parent.into()); | ||
1234 | match &body[self.pat_id] { | ||
1235 | Pat::Bind { mode, .. } => match mode { | ||
1236 | BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, | ||
1237 | _ => false, | ||
1238 | }, | ||
1239 | _ => false, | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { | ||
1244 | self.parent.into() | ||
1245 | } | ||
1246 | |||
1247 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1248 | self.parent(db).module(db) | ||
1249 | } | ||
1250 | |||
1251 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
1252 | let def = DefWithBodyId::from(self.parent); | ||
1253 | let infer = db.infer(def); | ||
1254 | let ty = infer[self.pat_id].clone(); | ||
1255 | let krate = def.module(db.upcast()).krate(); | ||
1256 | Type::new(db, krate, def, ty) | ||
1257 | } | ||
1258 | |||
1259 | pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> { | ||
1260 | let (_body, source_map) = db.body_with_source_map(self.parent.into()); | ||
1261 | let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... | ||
1262 | let root = src.file_syntax(db.upcast()); | ||
1263 | src.map(|ast| { | ||
1264 | ast.map_left(|it| it.cast().unwrap().to_node(&root)).map_right(|it| it.to_node(&root)) | ||
1265 | }) | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1270 | pub struct Label { | ||
1271 | pub(crate) parent: DefWithBodyId, | ||
1272 | pub(crate) label_id: LabelId, | ||
1273 | } | ||
1274 | |||
1275 | impl Label { | ||
1276 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1277 | self.parent(db).module(db) | ||
1278 | } | ||
1279 | |||
1280 | pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { | ||
1281 | self.parent.into() | ||
1282 | } | ||
1283 | |||
1284 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1285 | let body = db.body(self.parent.into()); | ||
1286 | body[self.label_id].name.clone() | ||
1287 | } | ||
1288 | |||
1289 | pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> { | ||
1290 | let (_body, source_map) = db.body_with_source_map(self.parent.into()); | ||
1291 | let src = source_map.label_syntax(self.label_id); | ||
1292 | let root = src.file_syntax(db.upcast()); | ||
1293 | src.map(|ast| ast.to_node(&root)) | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1298 | pub enum GenericParam { | ||
1299 | TypeParam(TypeParam), | ||
1300 | LifetimeParam(LifetimeParam), | ||
1301 | ConstParam(ConstParam), | ||
1302 | } | ||
1303 | impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); | ||
1304 | |||
1305 | impl GenericParam { | ||
1306 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1307 | match self { | ||
1308 | GenericParam::TypeParam(it) => it.module(db), | ||
1309 | GenericParam::LifetimeParam(it) => it.module(db), | ||
1310 | GenericParam::ConstParam(it) => it.module(db), | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1315 | match self { | ||
1316 | GenericParam::TypeParam(it) => it.name(db), | ||
1317 | GenericParam::LifetimeParam(it) => it.name(db), | ||
1318 | GenericParam::ConstParam(it) => it.name(db), | ||
1319 | } | ||
1320 | } | ||
1321 | } | ||
1322 | |||
1323 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1324 | pub struct TypeParam { | ||
1325 | pub(crate) id: TypeParamId, | ||
1326 | } | ||
1327 | |||
1328 | impl TypeParam { | ||
1329 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1330 | let params = db.generic_params(self.id.parent); | ||
1331 | params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing) | ||
1332 | } | ||
1333 | |||
1334 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1335 | self.id.parent.module(db.upcast()).into() | ||
1336 | } | ||
1337 | |||
1338 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
1339 | let resolver = self.id.parent.resolver(db.upcast()); | ||
1340 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1341 | let ty = Ty::Placeholder(self.id); | ||
1342 | Type { | ||
1343 | krate: self.id.parent.module(db.upcast()).krate(), | ||
1344 | ty: InEnvironment { value: ty, environment }, | ||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { | ||
1349 | db.generic_predicates_for_param(self.id) | ||
1350 | .into_iter() | ||
1351 | .filter_map(|pred| match &pred.value { | ||
1352 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1353 | Some(Trait::from(trait_ref.trait_)) | ||
1354 | } | ||
1355 | _ => None, | ||
1356 | }) | ||
1357 | .collect() | ||
1358 | } | ||
1359 | |||
1360 | pub fn default(self, db: &dyn HirDatabase) -> Option<Type> { | ||
1361 | let params = db.generic_defaults(self.id.parent); | ||
1362 | let local_idx = hir_ty::param_idx(db, self.id)?; | ||
1363 | let resolver = self.id.parent.resolver(db.upcast()); | ||
1364 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1365 | let ty = params.get(local_idx)?.clone(); | ||
1366 | let subst = Substs::type_params(db, self.id.parent); | ||
1367 | let ty = ty.subst(&subst.prefix(local_idx)); | ||
1368 | Some(Type { | ||
1369 | krate: self.id.parent.module(db.upcast()).krate(), | ||
1370 | ty: InEnvironment { value: ty, environment }, | ||
1371 | }) | ||
1372 | } | ||
1373 | } | ||
1374 | |||
1375 | impl HirDisplay for TypeParam { | ||
1376 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
1377 | write!(f, "{}", self.name(f.db))?; | ||
1378 | let bounds = f.db.generic_predicates_for_param(self.id); | ||
1379 | let substs = Substs::type_params(f.db, self.id.parent); | ||
1380 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | ||
1381 | if !(predicates.is_empty() || f.omit_verbose_types()) { | ||
1382 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | ||
1383 | } | ||
1384 | Ok(()) | ||
1385 | } | ||
1386 | } | ||
1387 | |||
1388 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1389 | pub struct LifetimeParam { | ||
1390 | pub(crate) id: LifetimeParamId, | ||
1391 | } | ||
1392 | |||
1393 | impl LifetimeParam { | ||
1394 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1395 | let params = db.generic_params(self.id.parent); | ||
1396 | params.lifetimes[self.id.local_id].name.clone() | ||
1397 | } | ||
1398 | |||
1399 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1400 | self.id.parent.module(db.upcast()).into() | ||
1401 | } | ||
1402 | |||
1403 | pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { | ||
1404 | self.id.parent.into() | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1409 | pub struct ConstParam { | ||
1410 | pub(crate) id: ConstParamId, | ||
1411 | } | ||
1412 | |||
1413 | impl ConstParam { | ||
1414 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1415 | let params = db.generic_params(self.id.parent); | ||
1416 | params.consts[self.id.local_id].name.clone() | ||
1417 | } | ||
1418 | |||
1419 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1420 | self.id.parent.module(db.upcast()).into() | ||
1421 | } | ||
1422 | |||
1423 | pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { | ||
1424 | self.id.parent.into() | ||
1425 | } | ||
1426 | |||
1427 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | ||
1428 | let def = self.id.parent; | ||
1429 | let krate = def.module(db.upcast()).krate(); | ||
1430 | Type::new(db, krate, def, db.const_param_ty(self.id)) | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1434 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
1435 | pub struct Impl { | ||
1436 | pub(crate) id: ImplId, | ||
1437 | } | ||
1438 | |||
1439 | impl Impl { | ||
1440 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> { | ||
1441 | let inherent = db.inherent_impls_in_crate(krate.id); | ||
1442 | let trait_ = db.trait_impls_in_crate(krate.id); | ||
1443 | |||
1444 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | ||
1445 | } | ||
1446 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<Impl> { | ||
1447 | let impls = db.trait_impls_in_crate(krate.id); | ||
1448 | impls.for_trait(trait_.id).map(Self::from).collect() | ||
1449 | } | ||
1450 | |||
1451 | // FIXME: the return type is wrong. This should be a hir version of | ||
1452 | // `TraitRef` (ie, resolved `TypeRef`). | ||
1453 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | ||
1454 | db.impl_data(self.id).target_trait.clone() | ||
1455 | } | ||
1456 | |||
1457 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { | ||
1458 | let impl_data = db.impl_data(self.id); | ||
1459 | let resolver = self.id.resolver(db.upcast()); | ||
1460 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | ||
1461 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1462 | let ty = Ty::from_hir(&ctx, &impl_data.target_type); | ||
1463 | Type { | ||
1464 | krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
1465 | ty: InEnvironment { value: ty, environment }, | ||
1466 | } | ||
1467 | } | ||
1468 | |||
1469 | pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> { | ||
1470 | db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() | ||
1471 | } | ||
1472 | |||
1473 | pub fn is_negative(self, db: &dyn HirDatabase) -> bool { | ||
1474 | db.impl_data(self.id).is_negative | ||
1475 | } | ||
1476 | |||
1477 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1478 | self.id.lookup(db.upcast()).container.module(db.upcast()).into() | ||
1479 | } | ||
1480 | |||
1481 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
1482 | Crate { id: self.module(db).id.krate() } | ||
1483 | } | ||
1484 | |||
1485 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { | ||
1486 | let src = self.source(db)?; | ||
1487 | let item = src.file_id.is_builtin_derive(db.upcast())?; | ||
1488 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); | ||
1489 | |||
1490 | // FIXME: handle `cfg_attr` | ||
1491 | let attr = item | ||
1492 | .value | ||
1493 | .attrs() | ||
1494 | .filter_map(|it| { | ||
1495 | let path = ModPath::from_src(it.path()?, &hygenic)?; | ||
1496 | if path.as_ident()?.to_string() == "derive" { | ||
1497 | Some(it) | ||
1498 | } else { | ||
1499 | None | ||
1500 | } | ||
1501 | }) | ||
1502 | .last()?; | ||
1503 | |||
1504 | Some(item.with_value(attr)) | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1508 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
1509 | pub struct Type { | ||
1510 | krate: CrateId, | ||
1511 | ty: InEnvironment<Ty>, | ||
1512 | } | ||
1513 | |||
1514 | impl Type { | ||
1515 | pub(crate) fn new_with_resolver( | ||
1516 | db: &dyn HirDatabase, | ||
1517 | resolver: &Resolver, | ||
1518 | ty: Ty, | ||
1519 | ) -> Option<Type> { | ||
1520 | let krate = resolver.krate()?; | ||
1521 | Some(Type::new_with_resolver_inner(db, krate, resolver, ty)) | ||
1522 | } | ||
1523 | pub(crate) fn new_with_resolver_inner( | ||
1524 | db: &dyn HirDatabase, | ||
1525 | krate: CrateId, | ||
1526 | resolver: &Resolver, | ||
1527 | ty: Ty, | ||
1528 | ) -> Type { | ||
1529 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1530 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
1531 | } | ||
1532 | |||
1533 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | ||
1534 | let resolver = lexical_env.resolver(db.upcast()); | ||
1535 | let environment = TraitEnvironment::lower(db, &resolver); | ||
1536 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
1537 | } | ||
1538 | |||
1539 | fn from_def( | ||
1540 | db: &dyn HirDatabase, | ||
1541 | krate: CrateId, | ||
1542 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, | ||
1543 | ) -> Type { | ||
1544 | let substs = Substs::build_for_def(db, def).fill_with_unknown().build(); | ||
1545 | let ty = db.ty(def.into()).subst(&substs); | ||
1546 | Type::new(db, krate, def, ty) | ||
1547 | } | ||
1548 | |||
1549 | pub fn is_unit(&self) -> bool { | ||
1550 | matches!( | ||
1551 | self.ty.value, | ||
1552 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. }) | ||
1553 | ) | ||
1554 | } | ||
1555 | pub fn is_bool(&self) -> bool { | ||
1556 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | ||
1557 | } | ||
1558 | |||
1559 | pub fn is_mutable_reference(&self) -> bool { | ||
1560 | matches!( | ||
1561 | self.ty.value, | ||
1562 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(Mutability::Mut), .. }) | ||
1563 | ) | ||
1564 | } | ||
1565 | |||
1566 | pub fn remove_ref(&self) -> Option<Type> { | ||
1567 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_), .. }) = self.ty.value { | ||
1568 | self.ty.value.substs().map(|substs| self.derived(substs[0].clone())) | ||
1569 | } else { | ||
1570 | None | ||
1571 | } | ||
1572 | } | ||
1573 | |||
1574 | pub fn is_unknown(&self) -> bool { | ||
1575 | matches!(self.ty.value, Ty::Unknown) | ||
1576 | } | ||
1577 | |||
1578 | /// Checks that particular type `ty` implements `std::future::Future`. | ||
1579 | /// This function is used in `.await` syntax completion. | ||
1580 | pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { | ||
1581 | // No special case for the type of async block, since Chalk can figure it out. | ||
1582 | |||
1583 | let krate = self.krate; | ||
1584 | |||
1585 | let std_future_trait = | ||
1586 | db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait()); | ||
1587 | let std_future_trait = match std_future_trait { | ||
1588 | Some(it) => it, | ||
1589 | None => return false, | ||
1590 | }; | ||
1591 | |||
1592 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | ||
1593 | method_resolution::implements_trait( | ||
1594 | &canonical_ty, | ||
1595 | db, | ||
1596 | self.ty.environment.clone(), | ||
1597 | krate, | ||
1598 | std_future_trait, | ||
1599 | ) | ||
1600 | } | ||
1601 | |||
1602 | /// Checks that particular type `ty` implements `std::ops::FnOnce`. | ||
1603 | /// | ||
1604 | /// This function can be used to check if a particular type is callable, since FnOnce is a | ||
1605 | /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce. | ||
1606 | pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool { | ||
1607 | let krate = self.krate; | ||
1608 | |||
1609 | let fnonce_trait = match FnTrait::FnOnce.get_id(db, krate) { | ||
1610 | Some(it) => it, | ||
1611 | None => return false, | ||
1612 | }; | ||
1613 | |||
1614 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | ||
1615 | method_resolution::implements_trait_unique( | ||
1616 | &canonical_ty, | ||
1617 | db, | ||
1618 | self.ty.environment.clone(), | ||
1619 | krate, | ||
1620 | fnonce_trait, | ||
1621 | ) | ||
1622 | } | ||
1623 | |||
1624 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { | ||
1625 | let trait_ref = hir_ty::TraitRef { | ||
1626 | trait_: trait_.id, | ||
1627 | substs: Substs::build_for_def(db, trait_.id) | ||
1628 | .push(self.ty.value.clone()) | ||
1629 | .fill(args.iter().map(|t| t.ty.value.clone())) | ||
1630 | .build(), | ||
1631 | }; | ||
1632 | |||
1633 | let goal = Canonical { | ||
1634 | value: hir_ty::InEnvironment::new( | ||
1635 | self.ty.environment.clone(), | ||
1636 | hir_ty::Obligation::Trait(trait_ref), | ||
1637 | ), | ||
1638 | kinds: Arc::new([]), | ||
1639 | }; | ||
1640 | |||
1641 | db.trait_solve(self.krate, goal).is_some() | ||
1642 | } | ||
1643 | |||
1644 | pub fn normalize_trait_assoc_type( | ||
1645 | &self, | ||
1646 | db: &dyn HirDatabase, | ||
1647 | trait_: Trait, | ||
1648 | args: &[Type], | ||
1649 | alias: TypeAlias, | ||
1650 | ) -> Option<Type> { | ||
1651 | let subst = Substs::build_for_def(db, trait_.id) | ||
1652 | .push(self.ty.value.clone()) | ||
1653 | .fill(args.iter().map(|t| t.ty.value.clone())) | ||
1654 | .build(); | ||
1655 | let predicate = ProjectionPredicate { | ||
1656 | projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst }, | ||
1657 | ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)), | ||
1658 | }; | ||
1659 | let goal = Canonical { | ||
1660 | value: InEnvironment::new( | ||
1661 | self.ty.environment.clone(), | ||
1662 | Obligation::Projection(predicate), | ||
1663 | ), | ||
1664 | kinds: Arc::new([TyKind::General]), | ||
1665 | }; | ||
1666 | |||
1667 | match db.trait_solve(self.krate, goal)? { | ||
1668 | Solution::Unique(SolutionVariables(subst)) => subst.value.first().cloned(), | ||
1669 | Solution::Ambig(_) => None, | ||
1670 | } | ||
1671 | .map(|ty| Type { | ||
1672 | krate: self.krate, | ||
1673 | ty: InEnvironment { value: ty, environment: Arc::clone(&self.ty.environment) }, | ||
1674 | }) | ||
1675 | } | ||
1676 | |||
1677 | pub fn is_copy(&self, db: &dyn HirDatabase) -> bool { | ||
1678 | let lang_item = db.lang_item(self.krate, SmolStr::new("copy")); | ||
1679 | let copy_trait = match lang_item { | ||
1680 | Some(LangItemTarget::TraitId(it)) => it, | ||
1681 | _ => return false, | ||
1682 | }; | ||
1683 | self.impls_trait(db, copy_trait.into(), &[]) | ||
1684 | } | ||
1685 | |||
1686 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { | ||
1687 | let def = match self.ty.value { | ||
1688 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), | ||
1689 | _ => None, | ||
1690 | }; | ||
1691 | |||
1692 | let sig = self.ty.value.callable_sig(db)?; | ||
1693 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | ||
1694 | } | ||
1695 | |||
1696 | pub fn is_closure(&self) -> bool { | ||
1697 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) | ||
1698 | } | ||
1699 | |||
1700 | pub fn is_fn(&self) -> bool { | ||
1701 | matches!( | ||
1702 | &self.ty.value, | ||
1703 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. }) | ||
1704 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. }) | ||
1705 | ) | ||
1706 | } | ||
1707 | |||
1708 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | ||
1709 | let adt_id = match self.ty.value { | ||
1710 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, | ||
1711 | _ => return false, | ||
1712 | }; | ||
1713 | |||
1714 | let adt = adt_id.into(); | ||
1715 | match adt { | ||
1716 | Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)), | ||
1717 | _ => false, | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | pub fn is_raw_ptr(&self) -> bool { | ||
1722 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | ||
1723 | } | ||
1724 | |||
1725 | pub fn contains_unknown(&self) -> bool { | ||
1726 | return go(&self.ty.value); | ||
1727 | |||
1728 | fn go(ty: &Ty) -> bool { | ||
1729 | match ty { | ||
1730 | Ty::Unknown => true, | ||
1731 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(go), | ||
1732 | _ => false, | ||
1733 | } | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | ||
1738 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1739 | let variant_id = match a_ty.ctor { | ||
1740 | TypeCtor::Adt(AdtId::StructId(s)) => s.into(), | ||
1741 | TypeCtor::Adt(AdtId::UnionId(u)) => u.into(), | ||
1742 | _ => return Vec::new(), | ||
1743 | }; | ||
1744 | |||
1745 | return db | ||
1746 | .field_types(variant_id) | ||
1747 | .iter() | ||
1748 | .map(|(local_id, ty)| { | ||
1749 | let def = Field { parent: variant_id.into(), id: local_id }; | ||
1750 | let ty = ty.clone().subst(&a_ty.parameters); | ||
1751 | (def, self.derived(ty)) | ||
1752 | }) | ||
1753 | .collect(); | ||
1754 | }; | ||
1755 | Vec::new() | ||
1756 | } | ||
1757 | |||
1758 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | ||
1759 | let mut res = Vec::new(); | ||
1760 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1761 | if let TypeCtor::Tuple { .. } = a_ty.ctor { | ||
1762 | for ty in a_ty.parameters.iter() { | ||
1763 | let ty = ty.clone(); | ||
1764 | res.push(self.derived(ty)); | ||
1765 | } | ||
1766 | } | ||
1767 | }; | ||
1768 | res | ||
1769 | } | ||
1770 | |||
1771 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | ||
1772 | // There should be no inference vars in types passed here | ||
1773 | // FIXME check that? | ||
1774 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | ||
1775 | let environment = self.ty.environment.clone(); | ||
1776 | let ty = InEnvironment { value: canonical, environment }; | ||
1777 | autoderef(db, Some(self.krate), ty) | ||
1778 | .map(|canonical| canonical.value) | ||
1779 | .map(move |ty| self.derived(ty)) | ||
1780 | } | ||
1781 | |||
1782 | // This would be nicer if it just returned an iterator, but that runs into | ||
1783 | // lifetime problems, because we need to borrow temp `CrateImplDefs`. | ||
1784 | pub fn iterate_assoc_items<T>( | ||
1785 | self, | ||
1786 | db: &dyn HirDatabase, | ||
1787 | krate: Crate, | ||
1788 | mut callback: impl FnMut(AssocItem) -> Option<T>, | ||
1789 | ) -> Option<T> { | ||
1790 | for krate in self.ty.value.def_crates(db, krate.id)? { | ||
1791 | let impls = db.inherent_impls_in_crate(krate); | ||
1792 | |||
1793 | for impl_def in impls.for_self_ty(&self.ty.value) { | ||
1794 | for &item in db.impl_data(*impl_def).items.iter() { | ||
1795 | if let Some(result) = callback(item.into()) { | ||
1796 | return Some(result); | ||
1797 | } | ||
1798 | } | ||
1799 | } | ||
1800 | } | ||
1801 | None | ||
1802 | } | ||
1803 | |||
1804 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { | ||
1805 | let ty = self.ty.value.strip_references(); | ||
1806 | let substs = match ty { | ||
1807 | Ty::Apply(apply_ty) => &apply_ty.parameters, | ||
1808 | Ty::Opaque(opaque_ty) => &opaque_ty.parameters, | ||
1809 | _ => return Either::Left(iter::empty()), | ||
1810 | }; | ||
1811 | |||
1812 | let iter = substs.iter().map(move |ty| self.derived(ty.clone())); | ||
1813 | Either::Right(iter) | ||
1814 | } | ||
1815 | |||
1816 | pub fn iterate_method_candidates<T>( | ||
1817 | &self, | ||
1818 | db: &dyn HirDatabase, | ||
1819 | krate: Crate, | ||
1820 | traits_in_scope: &FxHashSet<TraitId>, | ||
1821 | name: Option<&Name>, | ||
1822 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | ||
1823 | ) -> Option<T> { | ||
1824 | // There should be no inference vars in types passed here | ||
1825 | // FIXME check that? | ||
1826 | // FIXME replace Unknown by bound vars here | ||
1827 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | ||
1828 | |||
1829 | let env = self.ty.environment.clone(); | ||
1830 | let krate = krate.id; | ||
1831 | |||
1832 | method_resolution::iterate_method_candidates( | ||
1833 | &canonical, | ||
1834 | db, | ||
1835 | env, | ||
1836 | krate, | ||
1837 | traits_in_scope, | ||
1838 | name, | ||
1839 | method_resolution::LookupMode::MethodCall, | ||
1840 | |ty, it| match it { | ||
1841 | AssocItemId::FunctionId(f) => callback(ty, f.into()), | ||
1842 | _ => None, | ||
1843 | }, | ||
1844 | ) | ||
1845 | } | ||
1846 | |||
1847 | pub fn iterate_path_candidates<T>( | ||
1848 | &self, | ||
1849 | db: &dyn HirDatabase, | ||
1850 | krate: Crate, | ||
1851 | traits_in_scope: &FxHashSet<TraitId>, | ||
1852 | name: Option<&Name>, | ||
1853 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | ||
1854 | ) -> Option<T> { | ||
1855 | // There should be no inference vars in types passed here | ||
1856 | // FIXME check that? | ||
1857 | // FIXME replace Unknown by bound vars here | ||
1858 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | ||
1859 | |||
1860 | let env = self.ty.environment.clone(); | ||
1861 | let krate = krate.id; | ||
1862 | |||
1863 | method_resolution::iterate_method_candidates( | ||
1864 | &canonical, | ||
1865 | db, | ||
1866 | env, | ||
1867 | krate, | ||
1868 | traits_in_scope, | ||
1869 | name, | ||
1870 | method_resolution::LookupMode::Path, | ||
1871 | |ty, it| callback(ty, it.into()), | ||
1872 | ) | ||
1873 | } | ||
1874 | |||
1875 | pub fn as_adt(&self) -> Option<Adt> { | ||
1876 | let (adt, _subst) = self.ty.value.as_adt()?; | ||
1877 | Some(adt.into()) | ||
1878 | } | ||
1879 | |||
1880 | pub fn as_dyn_trait(&self) -> Option<Trait> { | ||
1881 | self.ty.value.dyn_trait().map(Into::into) | ||
1882 | } | ||
1883 | |||
1884 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | ||
1885 | self.ty.value.impl_trait_bounds(db).map(|it| { | ||
1886 | it.into_iter() | ||
1887 | .filter_map(|pred| match pred { | ||
1888 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1889 | Some(Trait::from(trait_ref.trait_)) | ||
1890 | } | ||
1891 | _ => None, | ||
1892 | }) | ||
1893 | .collect() | ||
1894 | }) | ||
1895 | } | ||
1896 | |||
1897 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1898 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | ||
1899 | } | ||
1900 | |||
1901 | // FIXME: provide required accessors such that it becomes implementable from outside. | ||
1902 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | ||
1903 | match (&self.ty.value, &other.ty.value) { | ||
1904 | (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor | ||
1905 | { | ||
1906 | TypeCtor::Ref(..) => match parameters.as_single() { | ||
1907 | Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor, | ||
1908 | _ => false, | ||
1909 | }, | ||
1910 | _ => a_original_ty.ctor == *ctor, | ||
1911 | }, | ||
1912 | _ => false, | ||
1913 | } | ||
1914 | } | ||
1915 | |||
1916 | fn derived(&self, ty: Ty) -> Type { | ||
1917 | Type { | ||
1918 | krate: self.krate, | ||
1919 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | ||
1924 | // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself. | ||
1925 | // We need a different order here. | ||
1926 | |||
1927 | fn walk_substs( | ||
1928 | db: &dyn HirDatabase, | ||
1929 | type_: &Type, | ||
1930 | substs: &Substs, | ||
1931 | cb: &mut impl FnMut(Type), | ||
1932 | ) { | ||
1933 | for ty in substs.iter() { | ||
1934 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
1935 | } | ||
1936 | } | ||
1937 | |||
1938 | fn walk_bounds( | ||
1939 | db: &dyn HirDatabase, | ||
1940 | type_: &Type, | ||
1941 | bounds: &[GenericPredicate], | ||
1942 | cb: &mut impl FnMut(Type), | ||
1943 | ) { | ||
1944 | for pred in bounds { | ||
1945 | match pred { | ||
1946 | GenericPredicate::Implemented(trait_ref) => { | ||
1947 | cb(type_.clone()); | ||
1948 | walk_substs(db, type_, &trait_ref.substs, cb); | ||
1949 | } | ||
1950 | _ => (), | ||
1951 | } | ||
1952 | } | ||
1953 | } | ||
1954 | |||
1955 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | ||
1956 | let ty = type_.ty.value.strip_references(); | ||
1957 | match ty { | ||
1958 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | ||
1959 | match ctor { | ||
1960 | TypeCtor::Adt(_) => { | ||
1961 | cb(type_.derived(ty.clone())); | ||
1962 | } | ||
1963 | TypeCtor::AssociatedType(_) => { | ||
1964 | if let Some(_) = ty.associated_type_parent_trait(db) { | ||
1965 | cb(type_.derived(ty.clone())); | ||
1966 | } | ||
1967 | } | ||
1968 | TypeCtor::OpaqueType(..) => { | ||
1969 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1970 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1971 | } | ||
1972 | } | ||
1973 | _ => (), | ||
1974 | } | ||
1975 | |||
1976 | // adt params, tuples, etc... | ||
1977 | walk_substs(db, type_, parameters, cb); | ||
1978 | } | ||
1979 | Ty::Opaque(opaque_ty) => { | ||
1980 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1981 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1982 | } | ||
1983 | |||
1984 | walk_substs(db, type_, &opaque_ty.parameters, cb); | ||
1985 | } | ||
1986 | Ty::Placeholder(_) => { | ||
1987 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1988 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1989 | } | ||
1990 | } | ||
1991 | Ty::Dyn(bounds) => { | ||
1992 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | ||
1993 | } | ||
1994 | |||
1995 | _ => (), | ||
1996 | } | ||
1997 | } | ||
1998 | |||
1999 | walk_type(db, self, &mut cb); | ||
2000 | } | ||
2001 | } | ||
2002 | |||
2003 | impl HirDisplay for Type { | ||
2004 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
2005 | self.ty.value.hir_fmt(f) | ||
2006 | } | ||
2007 | } | ||
2008 | |||
2009 | // FIXME: closures | ||
2010 | #[derive(Debug)] | ||
2011 | pub struct Callable { | ||
2012 | ty: Type, | ||
2013 | sig: FnSig, | ||
2014 | def: Option<CallableDefId>, | ||
2015 | pub(crate) is_bound_method: bool, | ||
2016 | } | ||
2017 | |||
2018 | pub enum CallableKind { | ||
2019 | Function(Function), | ||
2020 | TupleStruct(Struct), | ||
2021 | TupleEnumVariant(Variant), | ||
2022 | Closure, | ||
2023 | } | ||
2024 | |||
2025 | impl Callable { | ||
2026 | pub fn kind(&self) -> CallableKind { | ||
2027 | match self.def { | ||
2028 | Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), | ||
2029 | Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), | ||
2030 | Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()), | ||
2031 | None => CallableKind::Closure, | ||
2032 | } | ||
2033 | } | ||
2034 | pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { | ||
2035 | let func = match self.def { | ||
2036 | Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it, | ||
2037 | _ => return None, | ||
2038 | }; | ||
2039 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
2040 | let param_list = src.value.param_list()?; | ||
2041 | param_list.self_param() | ||
2042 | } | ||
2043 | pub fn n_params(&self) -> usize { | ||
2044 | self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } | ||
2045 | } | ||
2046 | pub fn params( | ||
2047 | &self, | ||
2048 | db: &dyn HirDatabase, | ||
2049 | ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> { | ||
2050 | let types = self | ||
2051 | .sig | ||
2052 | .params() | ||
2053 | .iter() | ||
2054 | .skip(if self.is_bound_method { 1 } else { 0 }) | ||
2055 | .map(|ty| self.ty.derived(ty.clone())); | ||
2056 | let patterns = match self.def { | ||
2057 | Some(CallableDefId::FunctionId(func)) => { | ||
2058 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
2059 | src.value.param_list().map(|param_list| { | ||
2060 | param_list | ||
2061 | .self_param() | ||
2062 | .map(|it| Some(Either::Left(it))) | ||
2063 | .filter(|_| !self.is_bound_method) | ||
2064 | .into_iter() | ||
2065 | .chain(param_list.params().map(|it| it.pat().map(Either::Right))) | ||
2066 | }) | ||
2067 | } | ||
2068 | _ => None, | ||
2069 | }; | ||
2070 | patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() | ||
2071 | } | ||
2072 | pub fn return_type(&self) -> Type { | ||
2073 | self.ty.derived(self.sig.ret().clone()) | ||
2074 | } | ||
2075 | } | ||
2076 | |||
2077 | /// For IDE only | ||
2078 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
2079 | pub enum ScopeDef { | ||
2080 | ModuleDef(ModuleDef), | ||
2081 | MacroDef(MacroDef), | ||
2082 | GenericParam(GenericParam), | ||
2083 | ImplSelfType(Impl), | ||
2084 | AdtSelfType(Adt), | ||
2085 | Local(Local), | ||
2086 | Unknown, | ||
2087 | } | ||
2088 | |||
2089 | impl ScopeDef { | ||
2090 | pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> { | ||
2091 | let mut items = ArrayVec::new(); | ||
2092 | |||
2093 | match (def.take_types(), def.take_values()) { | ||
2094 | (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())), | ||
2095 | (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())), | ||
2096 | (Some(m1), Some(m2)) => { | ||
2097 | // Some items, like unit structs and enum variants, are | ||
2098 | // returned as both a type and a value. Here we want | ||
2099 | // to de-duplicate them. | ||
2100 | if m1 != m2 { | ||
2101 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
2102 | items.push(ScopeDef::ModuleDef(m2.into())); | ||
2103 | } else { | ||
2104 | items.push(ScopeDef::ModuleDef(m1.into())); | ||
2105 | } | ||
2106 | } | ||
2107 | (None, None) => {} | ||
2108 | }; | ||
2109 | |||
2110 | if let Some(macro_def_id) = def.take_macros() { | ||
2111 | items.push(ScopeDef::MacroDef(macro_def_id.into())); | ||
2112 | } | ||
2113 | |||
2114 | if items.is_empty() { | ||
2115 | items.push(ScopeDef::Unknown); | ||
2116 | } | ||
2117 | |||
2118 | items | ||
2119 | } | ||
2120 | } | ||
2121 | |||
2122 | pub trait HasVisibility { | ||
2123 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility; | ||
2124 | fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool { | ||
2125 | let vis = self.visibility(db); | ||
2126 | vis.is_visible_from(db.upcast(), module.id) | ||
2127 | } | ||
2128 | } | ||
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 5343a036c..b1ebba516 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::{InactiveCode, UnresolvedModule, UnresolvedProcMacro}; | 2 | pub use hir_def::diagnostics::{ |
3 | InactiveCode, UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, | ||
4 | }; | ||
3 | pub use hir_expand::diagnostics::{ | 5 | pub use hir_expand::diagnostics::{ |
4 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, | 6 | Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder, |
5 | }; | 7 | }; |
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index b5814da11..179b9d51e 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs | |||
@@ -11,9 +11,8 @@ use hir_def::{ | |||
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | code_model::{BuiltinType, GenericParam}, | 14 | Adt, AssocItem, BuiltinType, DefWithBody, Field, GenericDef, GenericParam, Label, Local, |
15 | Adt, AssocItem, DefWithBody, Field, GenericDef, Label, Local, MacroDef, ModuleDef, Variant, | 15 | MacroDef, ModuleDef, Variant, VariantDef, |
16 | VariantDef, | ||
17 | }; | 16 | }; |
18 | 17 | ||
19 | macro_rules! from_id { | 18 | macro_rules! from_id { |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 769945c47..58adc8fd3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -20,50 +20,2117 @@ | |||
20 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
21 | 21 | ||
22 | mod semantics; | 22 | mod semantics; |
23 | pub mod db; | ||
24 | mod source_analyzer; | 23 | mod source_analyzer; |
25 | 24 | ||
26 | pub mod diagnostics; | ||
27 | |||
28 | mod from_id; | 25 | mod from_id; |
29 | mod code_model; | ||
30 | mod attrs; | 26 | mod attrs; |
31 | mod has_source; | 27 | mod has_source; |
32 | 28 | ||
29 | pub mod diagnostics; | ||
30 | pub mod db; | ||
31 | |||
32 | use std::{iter, sync::Arc}; | ||
33 | |||
34 | use arrayvec::ArrayVec; | ||
35 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | ||
36 | use either::Either; | ||
37 | use hir_def::{ | ||
38 | adt::{ReprKind, VariantData}, | ||
39 | expr::{BindingAnnotation, LabelId, Pat, PatId}, | ||
40 | item_tree::ItemTreeNode, | ||
41 | lang_item::LangItemTarget, | ||
42 | per_ns::PerNs, | ||
43 | resolver::{HasResolver, Resolver}, | ||
44 | src::HasSource as _, | ||
45 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | ||
46 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | ||
47 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | ||
48 | TypeParamId, UnionId, | ||
49 | }; | ||
50 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | ||
51 | use hir_ty::{ | ||
52 | autoderef, | ||
53 | display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, | ||
54 | method_resolution, | ||
55 | traits::{FnTrait, Solution, SolutionVariables}, | ||
56 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, | ||
57 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, | ||
58 | Ty, TyDefId, TyVariableKind, | ||
59 | }; | ||
60 | use rustc_hash::FxHashSet; | ||
61 | use stdx::{format_to, impl_from}; | ||
62 | use syntax::{ | ||
63 | ast::{self, AttrsOwner, NameOwner}, | ||
64 | AstNode, SmolStr, | ||
65 | }; | ||
66 | use tt::{Ident, Leaf, Literal, TokenTree}; | ||
67 | |||
68 | use crate::db::{DefDatabase, HirDatabase}; | ||
69 | |||
33 | pub use crate::{ | 70 | pub use crate::{ |
34 | attrs::{HasAttrs, Namespace}, | 71 | attrs::{HasAttrs, Namespace}, |
35 | code_model::{ | ||
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | ||
37 | ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, | ||
38 | GenericDef, GenericParam, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, | ||
39 | Module, ModuleDef, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, | ||
40 | Variant, VariantDef, | ||
41 | }, | ||
42 | has_source::HasSource, | 72 | has_source::HasSource, |
43 | semantics::{PathResolution, Semantics, SemanticsScope}, | 73 | semantics::{PathResolution, Semantics, SemanticsScope}, |
44 | }; | 74 | }; |
45 | 75 | ||
46 | pub use hir_def::{ | 76 | // Be careful with these re-exports. |
47 | adt::StructKind, | 77 | // |
48 | attr::{Attrs, Documentation}, | 78 | // `hir` is the boundary between the compiler and the IDE. It should try hard to |
49 | body::scope::ExprScopes, | 79 | // isolate the compiler from the ide, to allow the two to be refactored |
50 | builtin_type::BuiltinType, | 80 | // independently. Re-exporting something from the compiler is the sure way to |
51 | find_path::PrefixKind, | 81 | // breach the boundary. |
52 | import_map, | 82 | // |
53 | item_scope::ItemInNs, | 83 | // Generally, a refactoring which *removes* a name from this list is a good |
54 | nameres::ModuleSource, | 84 | // idea! |
55 | path::{ModPath, PathKind}, | 85 | pub use { |
56 | type_ref::{Mutability, TypeRef}, | 86 | hir_def::{ |
57 | visibility::Visibility, | 87 | adt::StructKind, |
58 | }; | 88 | attr::{Attrs, Documentation}, |
59 | pub use hir_expand::{ | 89 | body::scope::ExprScopes, |
60 | name::{known, AsName, Name}, | 90 | find_path::PrefixKind, |
61 | ExpandResult, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId, | 91 | import_map, |
62 | MacroFile, Origin, | 92 | item_scope::ItemInNs, |
93 | nameres::ModuleSource, | ||
94 | path::{ModPath, PathKind}, | ||
95 | type_ref::{Mutability, TypeRef}, | ||
96 | visibility::Visibility, | ||
97 | }, | ||
98 | hir_expand::{ | ||
99 | name::{known, Name}, | ||
100 | ExpandResult, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId, | ||
101 | MacroFile, Origin, | ||
102 | }, | ||
103 | hir_ty::display::HirDisplay, | ||
63 | }; | 104 | }; |
64 | pub use hir_ty::display::HirDisplay; | ||
65 | 105 | ||
66 | // These are negative re-exports: pub using these names is forbidden, they | 106 | // These are negative re-exports: pub using these names is forbidden, they |
67 | // should remain private to hir internals. | 107 | // should remain private to hir internals. |
68 | #[allow(unused)] | 108 | #[allow(unused)] |
69 | use {hir_def::path::Path, hir_expand::hygiene::Hygiene}; | 109 | use { |
110 | hir_def::path::Path, | ||
111 | hir_expand::{hygiene::Hygiene, name::AsName}, | ||
112 | }; | ||
113 | |||
114 | /// hir::Crate describes a single crate. It's the main interface with which | ||
115 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the | ||
116 | /// root module. | ||
117 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
118 | pub struct Crate { | ||
119 | pub(crate) id: CrateId, | ||
120 | } | ||
121 | |||
122 | #[derive(Debug)] | ||
123 | pub struct CrateDependency { | ||
124 | pub krate: Crate, | ||
125 | pub name: Name, | ||
126 | } | ||
127 | |||
128 | impl Crate { | ||
129 | pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> { | ||
130 | db.crate_graph()[self.id] | ||
131 | .dependencies | ||
132 | .iter() | ||
133 | .map(|dep| { | ||
134 | let krate = Crate { id: dep.crate_id }; | ||
135 | let name = dep.as_name(); | ||
136 | CrateDependency { krate, name } | ||
137 | }) | ||
138 | .collect() | ||
139 | } | ||
140 | |||
141 | // FIXME: add `transitive_reverse_dependencies`. | ||
142 | pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { | ||
143 | let crate_graph = db.crate_graph(); | ||
144 | crate_graph | ||
145 | .iter() | ||
146 | .filter(|&krate| { | ||
147 | crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id) | ||
148 | }) | ||
149 | .map(|id| Crate { id }) | ||
150 | .collect() | ||
151 | } | ||
152 | |||
153 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { | ||
154 | let def_map = db.crate_def_map(self.id); | ||
155 | Module { id: def_map.module_id(def_map.root()) } | ||
156 | } | ||
157 | |||
158 | pub fn root_file(self, db: &dyn HirDatabase) -> FileId { | ||
159 | db.crate_graph()[self.id].root_file_id | ||
160 | } | ||
161 | |||
162 | pub fn edition(self, db: &dyn HirDatabase) -> Edition { | ||
163 | db.crate_graph()[self.id].edition | ||
164 | } | ||
165 | |||
166 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> { | ||
167 | db.crate_graph()[self.id].display_name.clone() | ||
168 | } | ||
169 | |||
170 | pub fn query_external_importables( | ||
171 | self, | ||
172 | db: &dyn DefDatabase, | ||
173 | query: import_map::Query, | ||
174 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | ||
175 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { | ||
176 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | ||
177 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | ||
178 | }) | ||
179 | } | ||
180 | |||
181 | pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { | ||
182 | db.crate_graph().iter().map(|id| Crate { id }).collect() | ||
183 | } | ||
184 | |||
185 | /// Try to get the root URL of the documentation of a crate. | ||
186 | pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> { | ||
187 | // Look for #![doc(html_root_url = "...")] | ||
188 | let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into())); | ||
189 | let doc_attr_q = attrs.by_key("doc"); | ||
190 | |||
191 | if !doc_attr_q.exists() { | ||
192 | return None; | ||
193 | } | ||
194 | |||
195 | let doc_url = doc_attr_q.tt_values().map(|tt| { | ||
196 | let name = tt.token_trees.iter() | ||
197 | .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url")) | ||
198 | .skip(2) | ||
199 | .next(); | ||
200 | |||
201 | match name { | ||
202 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), | ||
203 | _ => None | ||
204 | } | ||
205 | }).flat_map(|t| t).next(); | ||
206 | |||
207 | doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") | ||
208 | } | ||
209 | } | ||
210 | |||
211 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
212 | pub struct Module { | ||
213 | pub(crate) id: ModuleId, | ||
214 | } | ||
215 | |||
216 | /// The defs which can be visible in the module. | ||
217 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
218 | pub enum ModuleDef { | ||
219 | Module(Module), | ||
220 | Function(Function), | ||
221 | Adt(Adt), | ||
222 | // Can't be directly declared, but can be imported. | ||
223 | Variant(Variant), | ||
224 | Const(Const), | ||
225 | Static(Static), | ||
226 | Trait(Trait), | ||
227 | TypeAlias(TypeAlias), | ||
228 | BuiltinType(BuiltinType), | ||
229 | } | ||
230 | impl_from!( | ||
231 | Module, | ||
232 | Function, | ||
233 | Adt(Struct, Enum, Union), | ||
234 | Variant, | ||
235 | Const, | ||
236 | Static, | ||
237 | Trait, | ||
238 | TypeAlias, | ||
239 | BuiltinType | ||
240 | for ModuleDef | ||
241 | ); | ||
242 | |||
243 | impl From<VariantDef> for ModuleDef { | ||
244 | fn from(var: VariantDef) -> Self { | ||
245 | match var { | ||
246 | VariantDef::Struct(t) => Adt::from(t).into(), | ||
247 | VariantDef::Union(t) => Adt::from(t).into(), | ||
248 | VariantDef::Variant(t) => t.into(), | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | impl ModuleDef { | ||
254 | pub fn module(self, db: &dyn HirDatabase) -> Option<Module> { | ||
255 | match self { | ||
256 | ModuleDef::Module(it) => it.parent(db), | ||
257 | ModuleDef::Function(it) => Some(it.module(db)), | ||
258 | ModuleDef::Adt(it) => Some(it.module(db)), | ||
259 | ModuleDef::Variant(it) => Some(it.module(db)), | ||
260 | ModuleDef::Const(it) => Some(it.module(db)), | ||
261 | ModuleDef::Static(it) => Some(it.module(db)), | ||
262 | ModuleDef::Trait(it) => Some(it.module(db)), | ||
263 | ModuleDef::TypeAlias(it) => Some(it.module(db)), | ||
264 | ModuleDef::BuiltinType(_) => None, | ||
265 | } | ||
266 | } | ||
267 | |||
268 | pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> { | ||
269 | let mut segments = Vec::new(); | ||
270 | segments.push(self.name(db)?.to_string()); | ||
271 | for m in self.module(db)?.path_to_root(db) { | ||
272 | segments.extend(m.name(db).map(|it| it.to_string())) | ||
273 | } | ||
274 | segments.reverse(); | ||
275 | Some(segments.join("::")) | ||
276 | } | ||
277 | |||
278 | pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> { | ||
279 | let module = match self { | ||
280 | ModuleDef::Module(it) => it.parent(db)?, | ||
281 | ModuleDef::Function(it) => return Some(it.visibility(db)), | ||
282 | ModuleDef::Adt(it) => it.module(db), | ||
283 | ModuleDef::Variant(it) => { | ||
284 | let parent = it.parent_enum(db); | ||
285 | let module = it.module(db); | ||
286 | return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent))); | ||
287 | } | ||
288 | ModuleDef::Const(it) => return Some(it.visibility(db)), | ||
289 | ModuleDef::Static(it) => it.module(db), | ||
290 | ModuleDef::Trait(it) => it.module(db), | ||
291 | ModuleDef::TypeAlias(it) => return Some(it.visibility(db)), | ||
292 | ModuleDef::BuiltinType(_) => return None, | ||
293 | }; | ||
294 | |||
295 | module.visibility_of(db, self) | ||
296 | } | ||
297 | |||
298 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
299 | match self { | ||
300 | ModuleDef::Adt(it) => Some(it.name(db)), | ||
301 | ModuleDef::Trait(it) => Some(it.name(db)), | ||
302 | ModuleDef::Function(it) => Some(it.name(db)), | ||
303 | ModuleDef::Variant(it) => Some(it.name(db)), | ||
304 | ModuleDef::TypeAlias(it) => Some(it.name(db)), | ||
305 | ModuleDef::Module(it) => it.name(db), | ||
306 | ModuleDef::Const(it) => it.name(db), | ||
307 | ModuleDef::Static(it) => it.name(db), | ||
308 | ModuleDef::BuiltinType(it) => Some(it.name()), | ||
309 | } | ||
310 | } | ||
311 | |||
312 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | ||
313 | let id = match self { | ||
314 | ModuleDef::Adt(it) => match it { | ||
315 | Adt::Struct(it) => it.id.into(), | ||
316 | Adt::Enum(it) => it.id.into(), | ||
317 | Adt::Union(it) => it.id.into(), | ||
318 | }, | ||
319 | ModuleDef::Trait(it) => it.id.into(), | ||
320 | ModuleDef::Function(it) => it.id.into(), | ||
321 | ModuleDef::TypeAlias(it) => it.id.into(), | ||
322 | ModuleDef::Module(it) => it.id.into(), | ||
323 | ModuleDef::Const(it) => it.id.into(), | ||
324 | ModuleDef::Static(it) => it.id.into(), | ||
325 | _ => return, | ||
326 | }; | ||
327 | |||
328 | let module = match self.module(db) { | ||
329 | Some(it) => it, | ||
330 | None => return, | ||
331 | }; | ||
332 | |||
333 | hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink) | ||
334 | } | ||
335 | } | ||
336 | |||
337 | impl Module { | ||
338 | /// Name of this module. | ||
339 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
340 | let def_map = self.id.def_map(db.upcast()); | ||
341 | let parent = def_map[self.id.local_id].parent?; | ||
342 | def_map[parent].children.iter().find_map(|(name, module_id)| { | ||
343 | if *module_id == self.id.local_id { | ||
344 | Some(name.clone()) | ||
345 | } else { | ||
346 | None | ||
347 | } | ||
348 | }) | ||
349 | } | ||
350 | |||
351 | /// Returns the crate this module is part of. | ||
352 | pub fn krate(self) -> Crate { | ||
353 | Crate { id: self.id.krate() } | ||
354 | } | ||
355 | |||
356 | /// Topmost parent of this module. Every module has a `crate_root`, but some | ||
357 | /// might be missing `krate`. This can happen if a module's file is not included | ||
358 | /// in the module tree of any target in `Cargo.toml`. | ||
359 | pub fn crate_root(self, db: &dyn HirDatabase) -> Module { | ||
360 | let def_map = db.crate_def_map(self.id.krate()); | ||
361 | Module { id: def_map.module_id(def_map.root()) } | ||
362 | } | ||
363 | |||
364 | /// Iterates over all child modules. | ||
365 | pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> { | ||
366 | let def_map = self.id.def_map(db.upcast()); | ||
367 | let children = def_map[self.id.local_id] | ||
368 | .children | ||
369 | .iter() | ||
370 | .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) }) | ||
371 | .collect::<Vec<_>>(); | ||
372 | children.into_iter() | ||
373 | } | ||
374 | |||