diff options
172 files changed, 6898 insertions, 3673 deletions
diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js index 2c7eedbe2..b499cd0fd 100644 --- a/.github/actions/github-release/main.js +++ b/.github/actions/github-release/main.js | |||
@@ -16,7 +16,7 @@ async function runOnce() { | |||
16 | const slug = process.env.GITHUB_REPOSITORY; | 16 | const slug = process.env.GITHUB_REPOSITORY; |
17 | const owner = slug.split('/')[0]; | 17 | const owner = slug.split('/')[0]; |
18 | const repo = slug.split('/')[1]; | 18 | const repo = slug.split('/')[1]; |
19 | const sha = process.env.GITHUB_SHA; | 19 | const sha = process.env.HEAD_SHA; |
20 | 20 | ||
21 | core.info(`files: ${files}`); | 21 | core.info(`files: ${files}`); |
22 | core.info(`name: ${name}`); | 22 | core.info(`name: ${name}`); |
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 00f299ff1..ed9191c49 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml | |||
@@ -97,7 +97,13 @@ jobs: | |||
97 | 97 | ||
98 | typescript: | 98 | typescript: |
99 | name: TypeScript | 99 | name: TypeScript |
100 | runs-on: ubuntu-latest | 100 | strategy: |
101 | fail-fast: false | ||
102 | matrix: | ||
103 | os: [ubuntu-latest, windows-latest, macos-latest] | ||
104 | |||
105 | runs-on: ${{ matrix.os }} | ||
106 | |||
101 | steps: | 107 | steps: |
102 | - name: Checkout repository | 108 | - name: Checkout repository |
103 | uses: actions/checkout@v2 | 109 | uses: actions/checkout@v2 |
@@ -111,10 +117,19 @@ jobs: | |||
111 | working-directory: ./editors/code | 117 | working-directory: ./editors/code |
112 | 118 | ||
113 | - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } | 119 | - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } |
120 | if: runner.os == 'Linux' | ||
114 | working-directory: ./editors/code | 121 | working-directory: ./editors/code |
115 | 122 | ||
116 | - run: npm run lint | 123 | - run: npm run lint |
117 | working-directory: ./editors/code | 124 | working-directory: ./editors/code |
118 | 125 | ||
126 | - name: Run vscode tests | ||
127 | uses: GabrielBB/[email protected] | ||
128 | env: | ||
129 | VSCODE_CLI: 1 | ||
130 | with: | ||
131 | run: npm --prefix ./editors/code test | ||
132 | # working-directory: ./editors/code # does not work: https://github.com/GabrielBB/xvfb-action/issues/8 | ||
133 | |||
119 | - run: npm run package --scripts-prepend-node-path | 134 | - run: npm run package --scripts-prepend-node-path |
120 | working-directory: ./editors/code | 135 | working-directory: ./editors/code |
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 29ac89549..1ae8ed1b6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml | |||
@@ -6,7 +6,7 @@ on: | |||
6 | push: | 6 | push: |
7 | branches: | 7 | branches: |
8 | - release | 8 | - release |
9 | - nightly | 9 | - trigger-nightly |
10 | 10 | ||
11 | env: | 11 | env: |
12 | CARGO_INCREMENTAL: 0 | 12 | CARGO_INCREMENTAL: 0 |
@@ -88,6 +88,9 @@ jobs: | |||
88 | - name: Checkout repository | 88 | - name: Checkout repository |
89 | uses: actions/checkout@v2 | 89 | uses: actions/checkout@v2 |
90 | 90 | ||
91 | - run: echo "::set-env name=HEAD_SHA::$(git rev-parse HEAD)" | ||
92 | - run: 'echo "HEAD_SHA: $HEAD_SHA"' | ||
93 | |||
91 | - uses: actions/download-artifact@v1 | 94 | - uses: actions/download-artifact@v1 |
92 | with: | 95 | with: |
93 | name: dist-macos-latest | 96 | name: dist-macos-latest |
diff --git a/.gitignore b/.gitignore index f835edef0..aef0fac33 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -7,4 +7,6 @@ crates/*/target | |||
7 | *.log | 7 | *.log |
8 | *.iml | 8 | *.iml |
9 | .vscode/settings.json | 9 | .vscode/settings.json |
10 | cargo-timing*.html | 10 | *.html |
11 | generated_assists.adoc | ||
12 | generated_features.adoc | ||
diff --git a/.vscode/launch.json b/.vscode/launch.json index 6a2fff906..8ca27d878 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json | |||
@@ -71,6 +71,28 @@ | |||
71 | } | 71 | } |
72 | }, | 72 | }, |
73 | { | 73 | { |
74 | // Used for testing the extension with a local build of the LSP server (in `target/release`) | ||
75 | // with all other extendions loaded. | ||
76 | "name": "Run With Extensions", | ||
77 | "type": "extensionHost", | ||
78 | "request": "launch", | ||
79 | "runtimeExecutable": "${execPath}", | ||
80 | "args": [ | ||
81 | "--disable-extension", "matklad.rust-analyzer", | ||
82 | "--extensionDevelopmentPath=${workspaceFolder}/editors/code" | ||
83 | ], | ||
84 | "outFiles": [ | ||
85 | "${workspaceFolder}/editors/code/out/**/*.js" | ||
86 | ], | ||
87 | "preLaunchTask": "Build Server (Release) and Extension", | ||
88 | "skipFiles": [ | ||
89 | "<node_internals>/**/*.js" | ||
90 | ], | ||
91 | "env": { | ||
92 | "__RA_LSP_SERVER_DEBUG": "${workspaceFolder}/target/release/rust-analyzer" | ||
93 | } | ||
94 | }, | ||
95 | { | ||
74 | // Used to attach LLDB to a running LSP server. | 96 | // Used to attach LLDB to a running LSP server. |
75 | // NOTE: Might require root permissions. For this run: | 97 | // NOTE: Might require root permissions. For this run: |
76 | // | 98 | // |
@@ -87,5 +109,17 @@ | |||
87 | "rust" | 109 | "rust" |
88 | ] | 110 | ] |
89 | }, | 111 | }, |
112 | { | ||
113 | "name": "Run Unit Tests", | ||
114 | "type": "extensionHost", | ||
115 | "request": "launch", | ||
116 | "runtimeExecutable": "${execPath}", | ||
117 | "args": [ | ||
118 | "--extensionDevelopmentPath=${workspaceFolder}/editors/code", | ||
119 | "--extensionTestsPath=${workspaceFolder}/editors/code/out/tests/unit" ], | ||
120 | "sourceMaps": true, | ||
121 | "outFiles": [ "${workspaceFolder}/editors/code/out/tests/unit/**/*.js" ], | ||
122 | "preLaunchTask": "Pretest" | ||
123 | } | ||
90 | ] | 124 | ] |
91 | } | 125 | } |
diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 0969ce89a..a25dff19e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json | |||
@@ -40,6 +40,18 @@ | |||
40 | "command": "cargo build --release --package rust-analyzer", | 40 | "command": "cargo build --release --package rust-analyzer", |
41 | "problemMatcher": "$rustc" | 41 | "problemMatcher": "$rustc" |
42 | }, | 42 | }, |
43 | { | ||
44 | "label": "Pretest", | ||
45 | "group": "build", | ||
46 | "isBackground": false, | ||
47 | "type": "npm", | ||
48 | "script": "pretest", | ||
49 | "path": "editors/code/", | ||
50 | "problemMatcher": { | ||
51 | "base": "$tsc", | ||
52 | "fileLocation": ["relative", "${workspaceFolder}/editors/code/"] | ||
53 | } | ||
54 | }, | ||
43 | 55 | ||
44 | { | 56 | { |
45 | "label": "Build Server and Extension", | 57 | "label": "Build Server and Extension", |
diff --git a/Cargo.lock b/Cargo.lock index 007f05b4d..5f88ad0c4 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -101,9 +101,9 @@ dependencies = [ | |||
101 | 101 | ||
102 | [[package]] | 102 | [[package]] |
103 | name = "cc" | 103 | name = "cc" |
104 | version = "1.0.53" | 104 | version = "1.0.54" |
105 | source = "registry+https://github.com/rust-lang/crates.io-index" | 105 | source = "registry+https://github.com/rust-lang/crates.io-index" |
106 | checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" | 106 | checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" |
107 | 107 | ||
108 | [[package]] | 108 | [[package]] |
109 | name = "cfg-if" | 109 | name = "cfg-if" |
@@ -114,7 +114,7 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | |||
114 | [[package]] | 114 | [[package]] |
115 | name = "chalk-derive" | 115 | name = "chalk-derive" |
116 | version = "0.10.1-dev" | 116 | version = "0.10.1-dev" |
117 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | 117 | source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c" |
118 | dependencies = [ | 118 | dependencies = [ |
119 | "proc-macro2", | 119 | "proc-macro2", |
120 | "quote", | 120 | "quote", |
@@ -125,51 +125,30 @@ dependencies = [ | |||
125 | [[package]] | 125 | [[package]] |
126 | name = "chalk-engine" | 126 | name = "chalk-engine" |
127 | version = "0.10.1-dev" | 127 | version = "0.10.1-dev" |
128 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | 128 | source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c" |
129 | dependencies = [ | 129 | dependencies = [ |
130 | "chalk-macros", | 130 | "chalk-derive", |
131 | "chalk-ir", | ||
131 | "rustc-hash", | 132 | "rustc-hash", |
132 | ] | 133 | ] |
133 | 134 | ||
134 | [[package]] | 135 | [[package]] |
135 | name = "chalk-ir" | 136 | name = "chalk-ir" |
136 | version = "0.10.1-dev" | 137 | version = "0.10.1-dev" |
137 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | 138 | source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c" |
138 | dependencies = [ | 139 | dependencies = [ |
139 | "chalk-derive", | 140 | "chalk-derive", |
140 | "chalk-engine", | ||
141 | "chalk-macros", | ||
142 | ] | ||
143 | |||
144 | [[package]] | ||
145 | name = "chalk-macros" | ||
146 | version = "0.10.1-dev" | ||
147 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | ||
148 | dependencies = [ | ||
149 | "lazy_static", | 141 | "lazy_static", |
150 | ] | 142 | ] |
151 | 143 | ||
152 | [[package]] | 144 | [[package]] |
153 | name = "chalk-rust-ir" | ||
154 | version = "0.10.1-dev" | ||
155 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | ||
156 | dependencies = [ | ||
157 | "chalk-derive", | ||
158 | "chalk-engine", | ||
159 | "chalk-ir", | ||
160 | "chalk-macros", | ||
161 | ] | ||
162 | |||
163 | [[package]] | ||
164 | name = "chalk-solve" | 145 | name = "chalk-solve" |
165 | version = "0.10.1-dev" | 146 | version = "0.10.1-dev" |
166 | source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" | 147 | source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c" |
167 | dependencies = [ | 148 | dependencies = [ |
168 | "chalk-derive", | 149 | "chalk-derive", |
169 | "chalk-engine", | 150 | "chalk-engine", |
170 | "chalk-ir", | 151 | "chalk-ir", |
171 | "chalk-macros", | ||
172 | "chalk-rust-ir", | ||
173 | "ena", | 152 | "ena", |
174 | "itertools", | 153 | "itertools", |
175 | "petgraph", | 154 | "petgraph", |
@@ -264,9 +243,9 @@ dependencies = [ | |||
264 | 243 | ||
265 | [[package]] | 244 | [[package]] |
266 | name = "crossbeam-queue" | 245 | name = "crossbeam-queue" |
267 | version = "0.2.1" | 246 | version = "0.2.2" |
268 | source = "registry+https://github.com/rust-lang/crates.io-index" | 247 | source = "registry+https://github.com/rust-lang/crates.io-index" |
269 | checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" | 248 | checksum = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2" |
270 | dependencies = [ | 249 | dependencies = [ |
271 | "cfg-if", | 250 | "cfg-if", |
272 | "crossbeam-utils", | 251 | "crossbeam-utils", |
@@ -382,9 +361,9 @@ dependencies = [ | |||
382 | 361 | ||
383 | [[package]] | 362 | [[package]] |
384 | name = "fst" | 363 | name = "fst" |
385 | version = "0.4.3" | 364 | version = "0.4.4" |
386 | source = "registry+https://github.com/rust-lang/crates.io-index" | 365 | source = "registry+https://github.com/rust-lang/crates.io-index" |
387 | checksum = "81f9cac32c1741cdf6b66be7dcf0d9c7f25ccf12f8aa84c16cfa31f9f14513b3" | 366 | checksum = "a7293de202dbfe786c0b3fe6110a027836c5438ed06db7b715c9955ff4bfea51" |
388 | 367 | ||
389 | [[package]] | 368 | [[package]] |
390 | name = "fuchsia-zircon" | 369 | name = "fuchsia-zircon" |
@@ -483,9 +462,9 @@ dependencies = [ | |||
483 | 462 | ||
484 | [[package]] | 463 | [[package]] |
485 | name = "indexmap" | 464 | name = "indexmap" |
486 | version = "1.3.2" | 465 | version = "1.4.0" |
487 | source = "registry+https://github.com/rust-lang/crates.io-index" | 466 | source = "registry+https://github.com/rust-lang/crates.io-index" |
488 | checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" | 467 | checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" |
489 | dependencies = [ | 468 | dependencies = [ |
490 | "autocfg", | 469 | "autocfg", |
491 | ] | 470 | ] |
@@ -610,9 +589,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" | |||
610 | 589 | ||
611 | [[package]] | 590 | [[package]] |
612 | name = "libc" | 591 | name = "libc" |
613 | version = "0.2.70" | 592 | version = "0.2.71" |
614 | source = "registry+https://github.com/rust-lang/crates.io-index" | 593 | source = "registry+https://github.com/rust-lang/crates.io-index" |
615 | checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" | 594 | checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" |
616 | 595 | ||
617 | [[package]] | 596 | [[package]] |
618 | name = "libloading" | 597 | name = "libloading" |
@@ -661,9 +640,9 @@ dependencies = [ | |||
661 | 640 | ||
662 | [[package]] | 641 | [[package]] |
663 | name = "lsp-types" | 642 | name = "lsp-types" |
664 | version = "0.74.1" | 643 | version = "0.74.2" |
665 | source = "registry+https://github.com/rust-lang/crates.io-index" | 644 | source = "registry+https://github.com/rust-lang/crates.io-index" |
666 | checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525" | 645 | checksum = "b360754e89e0e13c114245131382ba921d4ff1efabb918e549422938aaa8d392" |
667 | dependencies = [ | 646 | dependencies = [ |
668 | "base64", | 647 | "base64", |
669 | "bitflags", | 648 | "bitflags", |
@@ -830,9 +809,9 @@ dependencies = [ | |||
830 | 809 | ||
831 | [[package]] | 810 | [[package]] |
832 | name = "paste" | 811 | name = "paste" |
833 | version = "0.1.12" | 812 | version = "0.1.16" |
834 | source = "registry+https://github.com/rust-lang/crates.io-index" | 813 | source = "registry+https://github.com/rust-lang/crates.io-index" |
835 | checksum = "0a229b1c58c692edcaa5b9b0948084f130f55d2dcc15b02fcc5340b2b4521476" | 814 | checksum = "d508492eeb1e5c38ee696371bf7b9fc33c83d46a7d451606b96458fbbbdc2dec" |
836 | dependencies = [ | 815 | dependencies = [ |
837 | "paste-impl", | 816 | "paste-impl", |
838 | "proc-macro-hack", | 817 | "proc-macro-hack", |
@@ -840,9 +819,9 @@ dependencies = [ | |||
840 | 819 | ||
841 | [[package]] | 820 | [[package]] |
842 | name = "paste-impl" | 821 | name = "paste-impl" |
843 | version = "0.1.12" | 822 | version = "0.1.16" |
844 | source = "registry+https://github.com/rust-lang/crates.io-index" | 823 | source = "registry+https://github.com/rust-lang/crates.io-index" |
845 | checksum = "2e0bf239e447e67ff6d16a8bb5e4d4bd2343acf5066061c0e8e06ac5ba8ca68c" | 824 | checksum = "84f328a6a63192b333fce5fbb4be79db6758a4d518dfac6d54412f1492f72d32" |
846 | dependencies = [ | 825 | dependencies = [ |
847 | "proc-macro-hack", | 826 | "proc-macro-hack", |
848 | "proc-macro2", | 827 | "proc-macro2", |
@@ -858,9 +837,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" | |||
858 | 837 | ||
859 | [[package]] | 838 | [[package]] |
860 | name = "petgraph" | 839 | name = "petgraph" |
861 | version = "0.5.0" | 840 | version = "0.5.1" |
862 | source = "registry+https://github.com/rust-lang/crates.io-index" | 841 | source = "registry+https://github.com/rust-lang/crates.io-index" |
863 | checksum = "29c127eea4a29ec6c85d153c59dc1213f33ec74cead30fe4730aecc88cc1fd92" | 842 | checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" |
864 | dependencies = [ | 843 | dependencies = [ |
865 | "fixedbitset", | 844 | "fixedbitset", |
866 | "indexmap", | 845 | "indexmap", |
@@ -886,15 +865,15 @@ checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" | |||
886 | 865 | ||
887 | [[package]] | 866 | [[package]] |
888 | name = "proc-macro-hack" | 867 | name = "proc-macro-hack" |
889 | version = "0.5.15" | 868 | version = "0.5.16" |
890 | source = "registry+https://github.com/rust-lang/crates.io-index" | 869 | source = "registry+https://github.com/rust-lang/crates.io-index" |
891 | checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" | 870 | checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" |
892 | 871 | ||
893 | [[package]] | 872 | [[package]] |
894 | name = "proc-macro2" | 873 | name = "proc-macro2" |
895 | version = "1.0.13" | 874 | version = "1.0.18" |
896 | source = "registry+https://github.com/rust-lang/crates.io-index" | 875 | source = "registry+https://github.com/rust-lang/crates.io-index" |
897 | checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" | 876 | checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" |
898 | dependencies = [ | 877 | dependencies = [ |
899 | "unicode-xid", | 878 | "unicode-xid", |
900 | ] | 879 | ] |
@@ -1036,7 +1015,6 @@ version = "0.1.0" | |||
1036 | dependencies = [ | 1015 | dependencies = [ |
1037 | "arrayvec", | 1016 | "arrayvec", |
1038 | "chalk-ir", | 1017 | "chalk-ir", |
1039 | "chalk-rust-ir", | ||
1040 | "chalk-solve", | 1018 | "chalk-solve", |
1041 | "ena", | 1019 | "ena", |
1042 | "insta", | 1020 | "insta", |
@@ -1141,6 +1119,7 @@ dependencies = [ | |||
1141 | "memmap", | 1119 | "memmap", |
1142 | "ra_mbe", | 1120 | "ra_mbe", |
1143 | "ra_proc_macro", | 1121 | "ra_proc_macro", |
1122 | "ra_toolchain", | ||
1144 | "ra_tt", | 1123 | "ra_tt", |
1145 | "serde_derive", | 1124 | "serde_derive", |
1146 | "test_utils", | 1125 | "test_utils", |
@@ -1313,9 +1292,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" | |||
1313 | 1292 | ||
1314 | [[package]] | 1293 | [[package]] |
1315 | name = "regex" | 1294 | name = "regex" |
1316 | version = "1.3.7" | 1295 | version = "1.3.9" |
1317 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1296 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1318 | checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" | 1297 | checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" |
1319 | dependencies = [ | 1298 | dependencies = [ |
1320 | "aho-corasick", | 1299 | "aho-corasick", |
1321 | "memchr", | 1300 | "memchr", |
@@ -1325,9 +1304,9 @@ dependencies = [ | |||
1325 | 1304 | ||
1326 | [[package]] | 1305 | [[package]] |
1327 | name = "regex-syntax" | 1306 | name = "regex-syntax" |
1328 | version = "0.6.17" | 1307 | version = "0.6.18" |
1329 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1330 | checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" | 1309 | checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" |
1331 | 1310 | ||
1332 | [[package]] | 1311 | [[package]] |
1333 | name = "relative-path" | 1312 | name = "relative-path" |
@@ -1372,17 +1351,20 @@ dependencies = [ | |||
1372 | "lsp-types", | 1351 | "lsp-types", |
1373 | "parking_lot", | 1352 | "parking_lot", |
1374 | "pico-args", | 1353 | "pico-args", |
1354 | "ra_cfg", | ||
1375 | "ra_db", | 1355 | "ra_db", |
1376 | "ra_flycheck", | 1356 | "ra_flycheck", |
1377 | "ra_hir", | 1357 | "ra_hir", |
1378 | "ra_hir_def", | 1358 | "ra_hir_def", |
1379 | "ra_hir_ty", | 1359 | "ra_hir_ty", |
1380 | "ra_ide", | 1360 | "ra_ide", |
1361 | "ra_mbe", | ||
1381 | "ra_proc_macro_srv", | 1362 | "ra_proc_macro_srv", |
1382 | "ra_prof", | 1363 | "ra_prof", |
1383 | "ra_project_model", | 1364 | "ra_project_model", |
1384 | "ra_syntax", | 1365 | "ra_syntax", |
1385 | "ra_text_edit", | 1366 | "ra_text_edit", |
1367 | "ra_tt", | ||
1386 | "ra_vfs", | 1368 | "ra_vfs", |
1387 | "rand", | 1369 | "rand", |
1388 | "relative-path", | 1370 | "relative-path", |
@@ -1398,9 +1380,9 @@ dependencies = [ | |||
1398 | 1380 | ||
1399 | [[package]] | 1381 | [[package]] |
1400 | name = "rustc-ap-rustc_lexer" | 1382 | name = "rustc-ap-rustc_lexer" |
1401 | version = "656.0.0" | 1383 | version = "661.0.0" |
1402 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1403 | checksum = "9cbba98ec46e96a4663197dfa8c0378752de2006e314e5400c0ca74929d6692f" | 1385 | checksum = "a6d88abd7c634b52557e46fc7ba47644f0cbe45c358c33f51c532d60d1da239e" |
1404 | dependencies = [ | 1386 | dependencies = [ |
1405 | "unicode-xid", | 1387 | "unicode-xid", |
1406 | ] | 1388 | ] |
@@ -1419,9 +1401,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" | |||
1419 | 1401 | ||
1420 | [[package]] | 1402 | [[package]] |
1421 | name = "ryu" | 1403 | name = "ryu" |
1422 | version = "1.0.4" | 1404 | version = "1.0.5" |
1423 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1424 | checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" | 1406 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" |
1425 | 1407 | ||
1426 | [[package]] | 1408 | [[package]] |
1427 | name = "salsa" | 1409 | name = "salsa" |
@@ -1510,18 +1492,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | |||
1510 | 1492 | ||
1511 | [[package]] | 1493 | [[package]] |
1512 | name = "serde" | 1494 | name = "serde" |
1513 | version = "1.0.110" | 1495 | version = "1.0.111" |
1514 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1496 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1515 | checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" | 1497 | checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" |
1516 | dependencies = [ | 1498 | dependencies = [ |
1517 | "serde_derive", | 1499 | "serde_derive", |
1518 | ] | 1500 | ] |
1519 | 1501 | ||
1520 | [[package]] | 1502 | [[package]] |
1521 | name = "serde_derive" | 1503 | name = "serde_derive" |
1522 | version = "1.0.110" | 1504 | version = "1.0.111" |
1523 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1524 | checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" | 1506 | checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" |
1525 | dependencies = [ | 1507 | dependencies = [ |
1526 | "proc-macro2", | 1508 | "proc-macro2", |
1527 | "quote", | 1509 | "quote", |
@@ -1595,9 +1577,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | |||
1595 | 1577 | ||
1596 | [[package]] | 1578 | [[package]] |
1597 | name = "syn" | 1579 | name = "syn" |
1598 | version = "1.0.22" | 1580 | version = "1.0.30" |
1599 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1600 | checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" | 1582 | checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2" |
1601 | dependencies = [ | 1583 | dependencies = [ |
1602 | "proc-macro2", | 1584 | "proc-macro2", |
1603 | "quote", | 1585 | "quote", |
@@ -1654,7 +1636,11 @@ name = "test_utils" | |||
1654 | version = "0.1.0" | 1636 | version = "0.1.0" |
1655 | dependencies = [ | 1637 | dependencies = [ |
1656 | "difference", | 1638 | "difference", |
1639 | "ra_cfg", | ||
1640 | "relative-path", | ||
1641 | "rustc-hash", | ||
1657 | "serde_json", | 1642 | "serde_json", |
1643 | "stdx", | ||
1658 | "text-size", | 1644 | "text-size", |
1659 | ] | 1645 | ] |
1660 | 1646 | ||
@@ -1813,9 +1799,9 @@ dependencies = [ | |||
1813 | 1799 | ||
1814 | [[package]] | 1800 | [[package]] |
1815 | name = "yaml-rust" | 1801 | name = "yaml-rust" |
1816 | version = "0.4.3" | 1802 | version = "0.4.4" |
1817 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1803 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1818 | checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" | 1804 | checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" |
1819 | dependencies = [ | 1805 | dependencies = [ |
1820 | "linked-hash-map", | 1806 | "linked-hash-map", |
1821 | ] | 1807 | ] |
diff --git a/Cargo.toml b/Cargo.toml index c034e2424..5278b5a16 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
@@ -22,8 +22,6 @@ opt-level = 0 | |||
22 | opt-level = 0 | 22 | opt-level = 0 |
23 | [profile.release.package.chalk-derive] | 23 | [profile.release.package.chalk-derive] |
24 | opt-level = 0 | 24 | opt-level = 0 |
25 | [profile.release.package.chalk-macros] | ||
26 | opt-level = 0 | ||
27 | [profile.release.package.salsa-macros] | 25 | [profile.release.package.salsa-macros] |
28 | opt-level = 0 | 26 | opt-level = 0 |
29 | [profile.release.package.xtask] | 27 | [profile.release.package.xtask] |
@@ -27,9 +27,13 @@ If you want to **use** rust-analyzer's language server with your editor of | |||
27 | choice, check [the manual](https://rust-analyzer.github.io/manual.html) folder. It also contains some tips & tricks to help | 27 | choice, check [the manual](https://rust-analyzer.github.io/manual.html) folder. It also contains some tips & tricks to help |
28 | you be more productive when using rust-analyzer. | 28 | you be more productive when using rust-analyzer. |
29 | 29 | ||
30 | ## Getting in touch | 30 | ## Communication |
31 | 31 | ||
32 | We are on the rust-lang Zulip! | 32 | For usage and troubleshooting requests, please use "IDEs and Editors" category of the Rust forum: |
33 | |||
34 | https://users.rust-lang.org/c/ide/14 | ||
35 | |||
36 | For questions about development and implementation, join rls-2.0 working group on Zulip: | ||
33 | 37 | ||
34 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 | 38 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 |
35 | 39 | ||
@@ -2,6 +2,8 @@ status = [ | |||
2 | "Rust (ubuntu-latest)", | 2 | "Rust (ubuntu-latest)", |
3 | "Rust (windows-latest)", | 3 | "Rust (windows-latest)", |
4 | "Rust (macos-latest)", | 4 | "Rust (macos-latest)", |
5 | "TypeScript" | 5 | "TypeScript (ubuntu-latest)", |
6 | "TypeScript (windows-latest)", | ||
7 | "TypeScript (macos-latest)", | ||
6 | ] | 8 | ] |
7 | delete_merged_branches = true | 9 | delete_merged_branches = true |
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs index 6a675e812..776bddf91 100644 --- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | |||
@@ -4,9 +4,9 @@ use test_utils::mark; | |||
4 | 4 | ||
5 | use crate::{utils::FamousDefs, AssistContext, AssistId, Assists}; | 5 | use crate::{utils::FamousDefs, AssistContext, AssistId, Assists}; |
6 | 6 | ||
7 | // Assist add_from_impl_for_enum | 7 | // Assist: add_from_impl_for_enum |
8 | // | 8 | // |
9 | // Adds a From impl for an enum variant with one tuple field | 9 | // Adds a From impl for an enum variant with one tuple field. |
10 | // | 10 | // |
11 | // ``` | 11 | // ``` |
12 | // enum A { <|>One(u32) } | 12 | // enum A { <|>One(u32) } |
diff --git a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs new file mode 100644 index 000000000..beb5b7366 --- /dev/null +++ b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs | |||
@@ -0,0 +1,303 @@ | |||
1 | use ra_syntax::{ | ||
2 | ast::{self, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, | ||
3 | AstNode, SyntaxKind, TextRange, TextSize, | ||
4 | }; | ||
5 | use rustc_hash::FxHashSet; | ||
6 | |||
7 | use crate::{assist_context::AssistBuilder, AssistContext, AssistId, Assists}; | ||
8 | |||
9 | static ASSIST_NAME: &str = "introduce_named_lifetime"; | ||
10 | static ASSIST_LABEL: &str = "Introduce named lifetime"; | ||
11 | |||
12 | // Assist: introduce_named_lifetime | ||
13 | // | ||
14 | // Change an anonymous lifetime to a named lifetime. | ||
15 | // | ||
16 | // ``` | ||
17 | // impl Cursor<'_<|>> { | ||
18 | // fn node(self) -> &SyntaxNode { | ||
19 | // match self { | ||
20 | // Cursor::Replace(node) | Cursor::Before(node) => node, | ||
21 | // } | ||
22 | // } | ||
23 | // } | ||
24 | // ``` | ||
25 | // -> | ||
26 | // ``` | ||
27 | // impl<'a> Cursor<'a> { | ||
28 | // fn node(self) -> &SyntaxNode { | ||
29 | // match self { | ||
30 | // Cursor::Replace(node) | Cursor::Before(node) => node, | ||
31 | // } | ||
32 | // } | ||
33 | // } | ||
34 | // ``` | ||
35 | // FIXME: How can we handle renaming any one of multiple anonymous lifetimes? | ||
36 | // FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo | ||
37 | pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
38 | let lifetime_token = ctx | ||
39 | .find_token_at_offset(SyntaxKind::LIFETIME) | ||
40 | .filter(|lifetime| lifetime.text() == "'_")?; | ||
41 | if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::FnDef::cast) { | ||
42 | generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range()) | ||
43 | } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::ImplDef::cast) { | ||
44 | // only allow naming the last anonymous lifetime | ||
45 | lifetime_token.next_token().filter(|tok| tok.kind() == SyntaxKind::R_ANGLE)?; | ||
46 | generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range()) | ||
47 | } else { | ||
48 | None | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /// Generate the assist for the fn def case | ||
53 | fn generate_fn_def_assist( | ||
54 | acc: &mut Assists, | ||
55 | fn_def: &ast::FnDef, | ||
56 | lifetime_loc: TextRange, | ||
57 | ) -> Option<()> { | ||
58 | let param_list: ast::ParamList = fn_def.param_list()?; | ||
59 | let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.type_param_list())?; | ||
60 | let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end(); | ||
61 | let self_param = | ||
62 | // use the self if it's a reference and has no explicit lifetime | ||
63 | param_list.self_param().filter(|p| p.lifetime_token().is_none() && p.amp_token().is_some()); | ||
64 | // compute the location which implicitly has the same lifetime as the anonymous lifetime | ||
65 | let loc_needing_lifetime = if let Some(self_param) = self_param { | ||
66 | // if we have a self reference, use that | ||
67 | Some(self_param.self_token()?.text_range().start()) | ||
68 | } else { | ||
69 | // otherwise, if there's a single reference parameter without a named liftime, use that | ||
70 | let fn_params_without_lifetime: Vec<_> = param_list | ||
71 | .params() | ||
72 | .filter_map(|param| match param.ascribed_type() { | ||
73 | Some(ast::TypeRef::ReferenceType(ascribed_type)) | ||
74 | if ascribed_type.lifetime_token() == None => | ||
75 | { | ||
76 | Some(ascribed_type.amp_token()?.text_range().end()) | ||
77 | } | ||
78 | _ => None, | ||
79 | }) | ||
80 | .collect(); | ||
81 | match fn_params_without_lifetime.len() { | ||
82 | 1 => Some(fn_params_without_lifetime.into_iter().nth(0)?), | ||
83 | 0 => None, | ||
84 | // multiple unnnamed is invalid. assist is not applicable | ||
85 | _ => return None, | ||
86 | } | ||
87 | }; | ||
88 | acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { | ||
89 | add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param); | ||
90 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); | ||
91 | loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param))); | ||
92 | }) | ||
93 | } | ||
94 | |||
95 | /// Generate the assist for the impl def case | ||
96 | fn generate_impl_def_assist( | ||
97 | acc: &mut Assists, | ||
98 | impl_def: &ast::ImplDef, | ||
99 | lifetime_loc: TextRange, | ||
100 | ) -> Option<()> { | ||
101 | let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?; | ||
102 | let end_of_impl_kw = impl_def.impl_token()?.text_range().end(); | ||
103 | acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| { | ||
104 | add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param); | ||
105 | builder.replace(lifetime_loc, format!("'{}", new_lifetime_param)); | ||
106 | }) | ||
107 | } | ||
108 | |||
109 | /// Given a type parameter list, generate a unique lifetime parameter name | ||
110 | /// which is not in the list | ||
111 | fn generate_unique_lifetime_param_name( | ||
112 | existing_type_param_list: &Option<ast::TypeParamList>, | ||
113 | ) -> Option<char> { | ||
114 | match existing_type_param_list { | ||
115 | Some(type_params) => { | ||
116 | let used_lifetime_params: FxHashSet<_> = type_params | ||
117 | .lifetime_params() | ||
118 | .map(|p| p.syntax().text().to_string()[1..].to_owned()) | ||
119 | .collect(); | ||
120 | (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string())) | ||
121 | } | ||
122 | None => Some('a'), | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise | ||
127 | /// add new type params brackets with the lifetime parameter at `new_type_params_loc`. | ||
128 | fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>( | ||
129 | type_params_owner: &TypeParamsOwner, | ||
130 | builder: &mut AssistBuilder, | ||
131 | new_type_params_loc: TextSize, | ||
132 | new_lifetime_param: char, | ||
133 | ) { | ||
134 | match type_params_owner.type_param_list() { | ||
135 | // add the new lifetime parameter to an existing type param list | ||
136 | Some(type_params) => { | ||
137 | builder.insert( | ||
138 | (u32::from(type_params.syntax().text_range().end()) - 1).into(), | ||
139 | format!(", '{}", new_lifetime_param), | ||
140 | ); | ||
141 | } | ||
142 | // create a new type param list containing only the new lifetime parameter | ||
143 | None => { | ||
144 | builder.insert(new_type_params_loc, format!("<'{}>", new_lifetime_param)); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | #[cfg(test)] | ||
150 | mod tests { | ||
151 | use super::*; | ||
152 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
153 | |||
154 | #[test] | ||
155 | fn test_example_case() { | ||
156 | check_assist( | ||
157 | introduce_named_lifetime, | ||
158 | r#"impl Cursor<'_<|>> { | ||
159 | fn node(self) -> &SyntaxNode { | ||
160 | match self { | ||
161 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
162 | } | ||
163 | } | ||
164 | }"#, | ||
165 | r#"impl<'a> Cursor<'a> { | ||
166 | fn node(self) -> &SyntaxNode { | ||
167 | match self { | ||
168 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
169 | } | ||
170 | } | ||
171 | }"#, | ||
172 | ); | ||
173 | } | ||
174 | |||
175 | #[test] | ||
176 | fn test_example_case_simplified() { | ||
177 | check_assist( | ||
178 | introduce_named_lifetime, | ||
179 | r#"impl Cursor<'_<|>> {"#, | ||
180 | r#"impl<'a> Cursor<'a> {"#, | ||
181 | ); | ||
182 | } | ||
183 | |||
184 | #[test] | ||
185 | fn test_example_case_cursor_after_tick() { | ||
186 | check_assist( | ||
187 | introduce_named_lifetime, | ||
188 | r#"impl Cursor<'<|>_> {"#, | ||
189 | r#"impl<'a> Cursor<'a> {"#, | ||
190 | ); | ||
191 | } | ||
192 | |||
193 | #[test] | ||
194 | fn test_example_case_cursor_before_tick() { | ||
195 | check_assist( | ||
196 | introduce_named_lifetime, | ||
197 | r#"impl Cursor<<|>'_> {"#, | ||
198 | r#"impl<'a> Cursor<'a> {"#, | ||
199 | ); | ||
200 | } | ||
201 | |||
202 | #[test] | ||
203 | fn test_not_applicable_cursor_position() { | ||
204 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'_><|> {"#); | ||
205 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<|><'_> {"#); | ||
206 | } | ||
207 | |||
208 | #[test] | ||
209 | fn test_not_applicable_lifetime_already_name() { | ||
210 | check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'a<|>> {"#); | ||
211 | check_assist_not_applicable(introduce_named_lifetime, r#"fn my_fun<'a>() -> X<'a<|>>"#); | ||
212 | } | ||
213 | |||
214 | #[test] | ||
215 | fn test_with_type_parameter() { | ||
216 | check_assist( | ||
217 | introduce_named_lifetime, | ||
218 | r#"impl<T> Cursor<T, '_<|>>"#, | ||
219 | r#"impl<T, 'a> Cursor<T, 'a>"#, | ||
220 | ); | ||
221 | } | ||
222 | |||
223 | #[test] | ||
224 | fn test_with_existing_lifetime_name_conflict() { | ||
225 | check_assist( | ||
226 | introduce_named_lifetime, | ||
227 | r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#, | ||
228 | r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#, | ||
229 | ); | ||
230 | } | ||
231 | |||
232 | #[test] | ||
233 | fn test_function_return_value_anon_lifetime_param() { | ||
234 | check_assist( | ||
235 | introduce_named_lifetime, | ||
236 | r#"fn my_fun() -> X<'_<|>>"#, | ||
237 | r#"fn my_fun<'a>() -> X<'a>"#, | ||
238 | ); | ||
239 | } | ||
240 | |||
241 | #[test] | ||
242 | fn test_function_return_value_anon_reference_lifetime() { | ||
243 | check_assist( | ||
244 | introduce_named_lifetime, | ||
245 | r#"fn my_fun() -> &'_<|> X"#, | ||
246 | r#"fn my_fun<'a>() -> &'a X"#, | ||
247 | ); | ||
248 | } | ||
249 | |||
250 | #[test] | ||
251 | fn test_function_param_anon_lifetime() { | ||
252 | check_assist( | ||
253 | introduce_named_lifetime, | ||
254 | r#"fn my_fun(x: X<'_<|>>)"#, | ||
255 | r#"fn my_fun<'a>(x: X<'a>)"#, | ||
256 | ); | ||
257 | } | ||
258 | |||
259 | #[test] | ||
260 | fn test_function_add_lifetime_to_params() { | ||
261 | check_assist( | ||
262 | introduce_named_lifetime, | ||
263 | r#"fn my_fun(f: &Foo) -> X<'_<|>>"#, | ||
264 | r#"fn my_fun<'a>(f: &'a Foo) -> X<'a>"#, | ||
265 | ); | ||
266 | } | ||
267 | |||
268 | #[test] | ||
269 | fn test_function_add_lifetime_to_params_in_presence_of_other_lifetime() { | ||
270 | check_assist( | ||
271 | introduce_named_lifetime, | ||
272 | r#"fn my_fun<'other>(f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | ||
273 | r#"fn my_fun<'other, 'a>(f: &'a Foo, b: &'other Bar) -> X<'a>"#, | ||
274 | ); | ||
275 | } | ||
276 | |||
277 | #[test] | ||
278 | fn test_function_not_applicable_without_self_and_multiple_unnamed_param_lifetimes() { | ||
279 | // this is not permitted under lifetime elision rules | ||
280 | check_assist_not_applicable( | ||
281 | introduce_named_lifetime, | ||
282 | r#"fn my_fun(f: &Foo, b: &Bar) -> X<'_<|>>"#, | ||
283 | ); | ||
284 | } | ||
285 | |||
286 | #[test] | ||
287 | fn test_function_add_lifetime_to_self_ref_param() { | ||
288 | check_assist( | ||
289 | introduce_named_lifetime, | ||
290 | r#"fn my_fun<'other>(&self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | ||
291 | r#"fn my_fun<'other, 'a>(&'a self, f: &Foo, b: &'other Bar) -> X<'a>"#, | ||
292 | ); | ||
293 | } | ||
294 | |||
295 | #[test] | ||
296 | fn test_function_add_lifetime_to_param_with_non_ref_self() { | ||
297 | check_assist( | ||
298 | introduce_named_lifetime, | ||
299 | r#"fn my_fun<'other>(self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#, | ||
300 | r#"fn my_fun<'other, 'a>(self, f: &'a Foo, b: &'other Bar) -> X<'a>"#, | ||
301 | ); | ||
302 | } | ||
303 | } | ||
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index 30229edc2..897da2832 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs | |||
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, Assists}; | |||
23 | // ``` | 23 | // ``` |
24 | // | 24 | // |
25 | pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
26 | reorder::<ast::RecordLit>(acc, ctx.clone()).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) | 26 | reorder::<ast::RecordLit>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) |
27 | } | 27 | } |
28 | 28 | ||
29 | fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 29 | fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 9933f7a50..88ce9b62e 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -122,6 +122,7 @@ mod handlers { | |||
122 | mod flip_comma; | 122 | mod flip_comma; |
123 | mod flip_trait_bound; | 123 | mod flip_trait_bound; |
124 | mod inline_local_variable; | 124 | mod inline_local_variable; |
125 | mod introduce_named_lifetime; | ||
125 | mod introduce_variable; | 126 | mod introduce_variable; |
126 | mod invert_if; | 127 | mod invert_if; |
127 | mod merge_imports; | 128 | mod merge_imports; |
@@ -162,6 +163,7 @@ mod handlers { | |||
162 | flip_comma::flip_comma, | 163 | flip_comma::flip_comma, |
163 | flip_trait_bound::flip_trait_bound, | 164 | flip_trait_bound::flip_trait_bound, |
164 | inline_local_variable::inline_local_variable, | 165 | inline_local_variable::inline_local_variable, |
166 | introduce_named_lifetime::introduce_named_lifetime, | ||
165 | introduce_variable::introduce_variable, | 167 | introduce_variable::introduce_variable, |
166 | invert_if::invert_if, | 168 | invert_if::invert_if, |
167 | merge_imports::merge_imports, | 169 | merge_imports::merge_imports, |
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs index 250e56a69..d17504529 100644 --- a/crates/ra_assists/src/tests/generated.rs +++ b/crates/ra_assists/src/tests/generated.rs | |||
@@ -59,6 +59,25 @@ fn main() { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | #[test] | 61 | #[test] |
62 | fn doctest_add_from_impl_for_enum() { | ||
63 | check_doc_test( | ||
64 | "add_from_impl_for_enum", | ||
65 | r#####" | ||
66 | enum A { <|>One(u32) } | ||
67 | "#####, | ||
68 | r#####" | ||
69 | enum A { One(u32) } | ||
70 | |||
71 | impl From<u32> for A { | ||
72 | fn from(v: u32) -> Self { | ||
73 | A::One(v) | ||
74 | } | ||
75 | } | ||
76 | "#####, | ||
77 | ) | ||
78 | } | ||
79 | |||
80 | #[test] | ||
62 | fn doctest_add_function() { | 81 | fn doctest_add_function() { |
63 | check_doc_test( | 82 | check_doc_test( |
64 | "add_function", | 83 | "add_function", |
@@ -433,6 +452,31 @@ fn main() { | |||
433 | } | 452 | } |
434 | 453 | ||
435 | #[test] | 454 | #[test] |
455 | fn doctest_introduce_named_lifetime() { | ||
456 | check_doc_test( | ||
457 | "introduce_named_lifetime", | ||
458 | r#####" | ||
459 | impl Cursor<'_<|>> { | ||
460 | fn node(self) -> &SyntaxNode { | ||
461 | match self { | ||
462 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | "#####, | ||
467 | r#####" | ||
468 | impl<'a> Cursor<'a> { | ||
469 | fn node(self) -> &SyntaxNode { | ||
470 | match self { | ||
471 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | "#####, | ||
476 | ) | ||
477 | } | ||
478 | |||
479 | #[test] | ||
436 | fn doctest_introduce_variable() { | 480 | fn doctest_introduce_variable() { |
437 | check_doc_test( | 481 | check_doc_test( |
438 | "introduce_variable", | 482 | "introduce_variable", |
diff --git a/crates/ra_cfg/src/cfg_expr.rs b/crates/ra_cfg/src/cfg_expr.rs index 39d71851c..85b100c6a 100644 --- a/crates/ra_cfg/src/cfg_expr.rs +++ b/crates/ra_cfg/src/cfg_expr.rs | |||
@@ -88,13 +88,17 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> { | |||
88 | mod tests { | 88 | mod tests { |
89 | use super::*; | 89 | use super::*; |
90 | 90 | ||
91 | use mbe::ast_to_token_tree; | 91 | use mbe::{ast_to_token_tree, TokenMap}; |
92 | use ra_syntax::ast::{self, AstNode}; | 92 | use ra_syntax::ast::{self, AstNode}; |
93 | 93 | ||
94 | fn assert_parse_result(input: &str, expected: CfgExpr) { | 94 | fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) { |
95 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 95 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
96 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 96 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
97 | let (tt, _) = ast_to_token_tree(&tt).unwrap(); | 97 | ast_to_token_tree(&tt).unwrap() |
98 | } | ||
99 | |||
100 | fn assert_parse_result(input: &str, expected: CfgExpr) { | ||
101 | let (tt, _) = get_token_tree_generated(input); | ||
98 | assert_eq!(parse_cfg(&tt), expected); | 102 | assert_eq!(parse_cfg(&tt), expected); |
99 | } | 103 | } |
100 | 104 | ||
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index f8f767091..482a2f3e6 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -63,7 +63,7 @@ use std::sync::Arc; | |||
63 | 63 | ||
64 | use ra_cfg::CfgOptions; | 64 | use ra_cfg::CfgOptions; |
65 | use rustc_hash::FxHashMap; | 65 | use rustc_hash::FxHashMap; |
66 | use test_utils::{extract_offset, parse_fixture, parse_single_fixture, CURSOR_MARKER}; | 66 | use test_utils::{extract_offset, parse_fixture, parse_single_fixture, FixtureMeta, CURSOR_MARKER}; |
67 | 67 | ||
68 | use crate::{ | 68 | use crate::{ |
69 | input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, | 69 | input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, |
@@ -113,7 +113,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId | |||
113 | let fixture = parse_single_fixture(ra_fixture); | 113 | let fixture = parse_single_fixture(ra_fixture); |
114 | 114 | ||
115 | let crate_graph = if let Some(entry) = fixture { | 115 | let crate_graph = if let Some(entry) = fixture { |
116 | let meta = match parse_meta(&entry.meta) { | 116 | let meta = match ParsedMeta::from(&entry.meta) { |
117 | ParsedMeta::File(it) => it, | 117 | ParsedMeta::File(it) => it, |
118 | _ => panic!("with_single_file only support file meta"), | 118 | _ => panic!("with_single_file only support file meta"), |
119 | }; | 119 | }; |
@@ -170,7 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit | |||
170 | let mut file_position = None; | 170 | let mut file_position = None; |
171 | 171 | ||
172 | for entry in fixture.iter() { | 172 | for entry in fixture.iter() { |
173 | let meta = match parse_meta(&entry.meta) { | 173 | let meta = match ParsedMeta::from(&entry.meta) { |
174 | ParsedMeta::Root { path } => { | 174 | ParsedMeta::Root { path } => { |
175 | let source_root = std::mem::replace(&mut source_root, SourceRoot::new_local()); | 175 | let source_root = std::mem::replace(&mut source_root, SourceRoot::new_local()); |
176 | db.set_source_root(source_root_id, Arc::new(source_root)); | 176 | db.set_source_root(source_root_id, Arc::new(source_root)); |
@@ -258,53 +258,25 @@ struct FileMeta { | |||
258 | env: Env, | 258 | env: Env, |
259 | } | 259 | } |
260 | 260 | ||
261 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo) | 261 | impl From<&FixtureMeta> for ParsedMeta { |
262 | fn parse_meta(meta: &str) -> ParsedMeta { | 262 | fn from(meta: &FixtureMeta) -> Self { |
263 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); | 263 | match meta { |
264 | 264 | FixtureMeta::Root { path } => { | |
265 | if components[0] == "root" { | 265 | // `Self::Root` causes a false warning: 'variant is never constructed: `Root` ' |
266 | let path: RelativePathBuf = components[1].into(); | 266 | // see https://github.com/rust-lang/rust/issues/69018 |
267 | assert!(path.starts_with("/") && path.ends_with("/")); | 267 | ParsedMeta::Root { path: path.to_owned() } |
268 | return ParsedMeta::Root { path }; | ||
269 | } | ||
270 | |||
271 | let path: RelativePathBuf = components[0].into(); | ||
272 | assert!(path.starts_with("/")); | ||
273 | |||
274 | let mut krate = None; | ||
275 | let mut deps = Vec::new(); | ||
276 | let mut edition = Edition::Edition2018; | ||
277 | let mut cfg = CfgOptions::default(); | ||
278 | let mut env = Env::default(); | ||
279 | for component in components[1..].iter() { | ||
280 | let (key, value) = split1(component, ':').unwrap(); | ||
281 | match key { | ||
282 | "crate" => krate = Some(value.to_string()), | ||
283 | "deps" => deps = value.split(',').map(|it| it.to_string()).collect(), | ||
284 | "edition" => edition = Edition::from_str(&value).unwrap(), | ||
285 | "cfg" => { | ||
286 | for key in value.split(',') { | ||
287 | match split1(key, '=') { | ||
288 | None => cfg.insert_atom(key.into()), | ||
289 | Some((k, v)) => cfg.insert_key_value(k.into(), v.into()), | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | "env" => { | ||
294 | for key in value.split(',') { | ||
295 | if let Some((k, v)) = split1(key, '=') { | ||
296 | env.set(k, v.into()); | ||
297 | } | ||
298 | } | ||
299 | } | 268 | } |
300 | _ => panic!("bad component: {:?}", component), | 269 | FixtureMeta::File(f) => Self::File(FileMeta { |
270 | path: f.path.to_owned(), | ||
271 | krate: f.crate_name.to_owned(), | ||
272 | deps: f.deps.to_owned(), | ||
273 | cfg: f.cfg.to_owned(), | ||
274 | edition: f | ||
275 | .edition | ||
276 | .as_ref() | ||
277 | .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()), | ||
278 | env: Env::from(f.env.iter()), | ||
279 | }), | ||
301 | } | 280 | } |
302 | } | 281 | } |
303 | |||
304 | ParsedMeta::File(FileMeta { path, krate, deps, edition, cfg, env }) | ||
305 | } | ||
306 | |||
307 | fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> { | ||
308 | let idx = haystack.find(delim)?; | ||
309 | Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..])) | ||
310 | } | 282 | } |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index ab14e2d5e..4d2d3b48a 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -311,6 +311,21 @@ impl fmt::Display for Edition { | |||
311 | } | 311 | } |
312 | } | 312 | } |
313 | 313 | ||
314 | impl<'a, T> From<T> for Env | ||
315 | where | ||
316 | T: Iterator<Item = (&'a String, &'a String)>, | ||
317 | { | ||
318 | fn from(iter: T) -> Self { | ||
319 | let mut result = Self::default(); | ||
320 | |||
321 | for (k, v) in iter { | ||
322 | result.entries.insert(k.to_owned(), v.to_owned()); | ||
323 | } | ||
324 | |||
325 | result | ||
326 | } | ||
327 | } | ||
328 | |||
314 | impl Env { | 329 | impl Env { |
315 | pub fn set(&mut self, env: &str, value: String) { | 330 | pub fn set(&mut self, env: &str, value: String) { |
316 | self.entries.insert(env.to_owned(), value); | 331 | self.entries.insert(env.to_owned(), value); |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 840cfdfc8..4a06f3bcd 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -532,7 +532,7 @@ impl Adt { | |||
532 | Some(self.module(db).krate()) | 532 | Some(self.module(db).krate()) |
533 | } | 533 | } |
534 | 534 | ||
535 | pub fn name(&self, db: &dyn HirDatabase) -> Name { | 535 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
536 | match self { | 536 | match self { |
537 | Adt::Struct(s) => s.name(db), | 537 | Adt::Struct(s) => s.name(db), |
538 | Adt::Union(u) => u.name(db), | 538 | Adt::Union(u) => u.name(db), |
@@ -637,6 +637,10 @@ impl Function { | |||
637 | db.function_data(self.id).params.clone() | 637 | db.function_data(self.id).params.clone() |
638 | } | 638 | } |
639 | 639 | ||
640 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | ||
641 | db.function_data(self.id).is_unsafe | ||
642 | } | ||
643 | |||
640 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 644 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
641 | let _p = profile("Function::diagnostics"); | 645 | let _p = profile("Function::diagnostics"); |
642 | let infer = db.infer(self.id.into()); | 646 | let infer = db.infer(self.id.into()); |
@@ -1018,15 +1022,15 @@ impl ImplDef { | |||
1018 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() | 1022 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() |
1019 | } | 1023 | } |
1020 | 1024 | ||
1021 | pub fn target_trait(&self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1025 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1022 | db.impl_data(self.id).target_trait.clone() | 1026 | db.impl_data(self.id).target_trait.clone() |
1023 | } | 1027 | } |
1024 | 1028 | ||
1025 | pub fn target_type(&self, db: &dyn HirDatabase) -> TypeRef { | 1029 | pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef { |
1026 | db.impl_data(self.id).target_type.clone() | 1030 | db.impl_data(self.id).target_type.clone() |
1027 | } | 1031 | } |
1028 | 1032 | ||
1029 | pub fn target_ty(&self, db: &dyn HirDatabase) -> Type { | 1033 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { |
1030 | let impl_data = db.impl_data(self.id); | 1034 | let impl_data = db.impl_data(self.id); |
1031 | let resolver = self.id.resolver(db.upcast()); | 1035 | let resolver = self.id.resolver(db.upcast()); |
1032 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 1036 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
@@ -1038,23 +1042,23 @@ impl ImplDef { | |||
1038 | } | 1042 | } |
1039 | } | 1043 | } |
1040 | 1044 | ||
1041 | pub fn items(&self, db: &dyn HirDatabase) -> Vec<AssocItem> { | 1045 | pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> { |
1042 | db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() | 1046 | db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() |
1043 | } | 1047 | } |
1044 | 1048 | ||
1045 | pub fn is_negative(&self, db: &dyn HirDatabase) -> bool { | 1049 | pub fn is_negative(self, db: &dyn HirDatabase) -> bool { |
1046 | db.impl_data(self.id).is_negative | 1050 | db.impl_data(self.id).is_negative |
1047 | } | 1051 | } |
1048 | 1052 | ||
1049 | pub fn module(&self, db: &dyn HirDatabase) -> Module { | 1053 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
1050 | self.id.lookup(db.upcast()).container.module(db.upcast()).into() | 1054 | self.id.lookup(db.upcast()).container.module(db.upcast()).into() |
1051 | } | 1055 | } |
1052 | 1056 | ||
1053 | pub fn krate(&self, db: &dyn HirDatabase) -> Crate { | 1057 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { |
1054 | Crate { id: self.module(db).id.krate } | 1058 | Crate { id: self.module(db).id.krate } |
1055 | } | 1059 | } |
1056 | 1060 | ||
1057 | pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { | 1061 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { |
1058 | let src = self.source(db); | 1062 | let src = self.source(db); |
1059 | let item = src.file_id.is_builtin_derive(db.upcast())?; | 1063 | let item = src.file_id.is_builtin_derive(db.upcast())?; |
1060 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); | 1064 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); |
@@ -1190,6 +1194,10 @@ impl Type { | |||
1190 | ) | 1194 | ) |
1191 | } | 1195 | } |
1192 | 1196 | ||
1197 | pub fn is_raw_ptr(&self) -> bool { | ||
1198 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | ||
1199 | } | ||
1200 | |||
1193 | pub fn contains_unknown(&self) -> bool { | 1201 | pub fn contains_unknown(&self) -> bool { |
1194 | return go(&self.ty.value); | 1202 | return go(&self.ty.value); |
1195 | 1203 | ||
@@ -1363,6 +1371,7 @@ impl HirDisplay for Type { | |||
1363 | } | 1371 | } |
1364 | 1372 | ||
1365 | /// For IDE only | 1373 | /// For IDE only |
1374 | #[derive(Debug)] | ||
1366 | pub enum ScopeDef { | 1375 | pub enum ScopeDef { |
1367 | ModuleDef(ModuleDef), | 1376 | ModuleDef(ModuleDef), |
1368 | MacroDef(MacroDef), | 1377 | MacroDef(MacroDef), |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 4af0f046a..f4a6b0503 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -62,6 +62,7 @@ pub use crate::{ | |||
62 | 62 | ||
63 | pub use hir_def::{ | 63 | pub use hir_def::{ |
64 | adt::StructKind, | 64 | adt::StructKind, |
65 | attr::Attrs, | ||
65 | body::scope::ExprScopes, | 66 | body::scope::ExprScopes, |
66 | builtin_type::BuiltinType, | 67 | builtin_type::BuiltinType, |
67 | docs::Documentation, | 68 | docs::Documentation, |
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 576cd0c65..2eeba0572 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -81,18 +81,24 @@ impl Attrs { | |||
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { | 84 | pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { |
85 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); | 85 | let hygiene = Hygiene::new(db.upcast(), owner.file_id); |
86 | Attrs::new(owner.value, &hygiene) | 86 | Attrs::new(owner.value, &hygiene) |
87 | } | 87 | } |
88 | 88 | ||
89 | pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { | 89 | pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { |
90 | let docs = ast::CommentIter::from_syntax_node(owner.syntax()).doc_comment_text().map( | ||
91 | |docs_text| Attr { | ||
92 | input: Some(AttrInput::Literal(SmolStr::new(docs_text))), | ||
93 | path: ModPath::from(hir_expand::name!(doc)), | ||
94 | }, | ||
95 | ); | ||
90 | let mut attrs = owner.attrs().peekable(); | 96 | let mut attrs = owner.attrs().peekable(); |
91 | let entries = if attrs.peek().is_none() { | 97 | let entries = if attrs.peek().is_none() { |
92 | // Avoid heap allocation | 98 | // Avoid heap allocation |
93 | None | 99 | None |
94 | } else { | 100 | } else { |
95 | Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect()) | 101 | Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).chain(docs).collect()) |
96 | }; | 102 | }; |
97 | Attrs { entries } | 103 | Attrs { entries } |
98 | } | 104 | } |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index f5a7305dc..273036cee 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -29,7 +29,7 @@ use crate::{ | |||
29 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 29 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | /// A subset of Exander that only deals with cfg attributes. We only need it to | 32 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
33 | /// avoid cyclic queries in crate def map during enum processing. | 33 | /// avoid cyclic queries in crate def map during enum processing. |
34 | pub(crate) struct CfgExpander { | 34 | pub(crate) struct CfgExpander { |
35 | cfg_options: CfgOptions, | 35 | cfg_options: CfgOptions, |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e08d62dd6..f159f80af 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -28,7 +28,7 @@ use crate::{ | |||
28 | }, | 28 | }, |
29 | item_scope::BuiltinShadowMode, | 29 | item_scope::BuiltinShadowMode, |
30 | path::{GenericArgs, Path}, | 30 | path::{GenericArgs, Path}, |
31 | type_ref::{Mutability, TypeRef}, | 31 | type_ref::{Mutability, Rawness, TypeRef}, |
32 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 32 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, |
33 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 33 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
34 | }; | 34 | }; |
@@ -134,7 +134,7 @@ impl ExprCollector<'_> { | |||
134 | self.make_expr(expr, Err(SyntheticSyntax)) | 134 | self.make_expr(expr, Err(SyntheticSyntax)) |
135 | } | 135 | } |
136 | fn empty_block(&mut self) -> ExprId { | 136 | fn empty_block(&mut self) -> ExprId { |
137 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) | 137 | self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None }) |
138 | } | 138 | } |
139 | fn missing_expr(&mut self) -> ExprId { | 139 | fn missing_expr(&mut self) -> ExprId { |
140 | self.alloc_expr_desugared(Expr::Missing) | 140 | self.alloc_expr_desugared(Expr::Missing) |
@@ -215,7 +215,16 @@ impl ExprCollector<'_> { | |||
215 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 215 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
216 | ast::Expr::LoopExpr(e) => { | 216 | ast::Expr::LoopExpr(e) => { |
217 | let body = self.collect_block_opt(e.loop_body()); | 217 | let body = self.collect_block_opt(e.loop_body()); |
218 | self.alloc_expr(Expr::Loop { body }, syntax_ptr) | 218 | self.alloc_expr( |
219 | Expr::Loop { | ||
220 | body, | ||
221 | label: e | ||
222 | .label() | ||
223 | .and_then(|l| l.lifetime_token()) | ||
224 | .map(|l| Name::new_lifetime(&l)), | ||
225 | }, | ||
226 | syntax_ptr, | ||
227 | ) | ||
219 | } | 228 | } |
220 | ast::Expr::WhileExpr(e) => { | 229 | ast::Expr::WhileExpr(e) => { |
221 | let body = self.collect_block_opt(e.loop_body()); | 230 | let body = self.collect_block_opt(e.loop_body()); |
@@ -230,25 +239,56 @@ impl ExprCollector<'_> { | |||
230 | let pat = self.collect_pat(pat); | 239 | let pat = self.collect_pat(pat); |
231 | let match_expr = self.collect_expr_opt(condition.expr()); | 240 | let match_expr = self.collect_expr_opt(condition.expr()); |
232 | let placeholder_pat = self.missing_pat(); | 241 | let placeholder_pat = self.missing_pat(); |
233 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); | 242 | let break_ = |
243 | self.alloc_expr_desugared(Expr::Break { expr: None, label: None }); | ||
234 | let arms = vec![ | 244 | let arms = vec![ |
235 | MatchArm { pat, expr: body, guard: None }, | 245 | MatchArm { pat, expr: body, guard: None }, |
236 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, | 246 | MatchArm { pat: placeholder_pat, expr: break_, guard: None }, |
237 | ]; | 247 | ]; |
238 | let match_expr = | 248 | let match_expr = |
239 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); | 249 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
240 | return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); | 250 | return self.alloc_expr( |
251 | Expr::Loop { | ||
252 | body: match_expr, | ||
253 | label: e | ||
254 | .label() | ||
255 | .and_then(|l| l.lifetime_token()) | ||
256 | .map(|l| Name::new_lifetime(&l)), | ||
257 | }, | ||
258 | syntax_ptr, | ||
259 | ); | ||
241 | } | 260 | } |
242 | }, | 261 | }, |
243 | }; | 262 | }; |
244 | 263 | ||
245 | self.alloc_expr(Expr::While { condition, body }, syntax_ptr) | 264 | self.alloc_expr( |
265 | Expr::While { | ||
266 | condition, | ||
267 | body, | ||
268 | label: e | ||
269 | .label() | ||
270 | .and_then(|l| l.lifetime_token()) | ||
271 | .map(|l| Name::new_lifetime(&l)), | ||
272 | }, | ||
273 | syntax_ptr, | ||
274 | ) | ||
246 | } | 275 | } |
247 | ast::Expr::ForExpr(e) => { | 276 | ast::Expr::ForExpr(e) => { |
248 | let iterable = self.collect_expr_opt(e.iterable()); | 277 | let iterable = self.collect_expr_opt(e.iterable()); |
249 | let pat = self.collect_pat_opt(e.pat()); | 278 | let pat = self.collect_pat_opt(e.pat()); |
250 | let body = self.collect_block_opt(e.loop_body()); | 279 | let body = self.collect_block_opt(e.loop_body()); |
251 | self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) | 280 | self.alloc_expr( |
281 | Expr::For { | ||
282 | iterable, | ||
283 | pat, | ||
284 | body, | ||
285 | label: e | ||
286 | .label() | ||
287 | .and_then(|l| l.lifetime_token()) | ||
288 | .map(|l| Name::new_lifetime(&l)), | ||
289 | }, | ||
290 | syntax_ptr, | ||
291 | ) | ||
252 | } | 292 | } |
253 | ast::Expr::CallExpr(e) => { | 293 | ast::Expr::CallExpr(e) => { |
254 | let callee = self.collect_expr_opt(e.expr()); | 294 | let callee = self.collect_expr_opt(e.expr()); |
@@ -301,13 +341,16 @@ impl ExprCollector<'_> { | |||
301 | .unwrap_or(Expr::Missing); | 341 | .unwrap_or(Expr::Missing); |
302 | self.alloc_expr(path, syntax_ptr) | 342 | self.alloc_expr(path, syntax_ptr) |
303 | } | 343 | } |
304 | ast::Expr::ContinueExpr(_e) => { | 344 | ast::Expr::ContinueExpr(e) => self.alloc_expr( |
305 | // FIXME: labels | 345 | Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, |
306 | self.alloc_expr(Expr::Continue, syntax_ptr) | 346 | syntax_ptr, |
307 | } | 347 | ), |
308 | ast::Expr::BreakExpr(e) => { | 348 | ast::Expr::BreakExpr(e) => { |
309 | let expr = e.expr().map(|e| self.collect_expr(e)); | 349 | let expr = e.expr().map(|e| self.collect_expr(e)); |
310 | self.alloc_expr(Expr::Break { expr }, syntax_ptr) | 350 | self.alloc_expr( |
351 | Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, | ||
352 | syntax_ptr, | ||
353 | ) | ||
311 | } | 354 | } |
312 | ast::Expr::ParenExpr(e) => { | 355 | ast::Expr::ParenExpr(e) => { |
313 | let inner = self.collect_expr_opt(e.expr()); | 356 | let inner = self.collect_expr_opt(e.expr()); |
@@ -378,8 +421,21 @@ impl ExprCollector<'_> { | |||
378 | } | 421 | } |
379 | ast::Expr::RefExpr(e) => { | 422 | ast::Expr::RefExpr(e) => { |
380 | let expr = self.collect_expr_opt(e.expr()); | 423 | let expr = self.collect_expr_opt(e.expr()); |
381 | let mutability = Mutability::from_mutable(e.mut_token().is_some()); | 424 | let raw_tok = e.raw_token().is_some(); |
382 | self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) | 425 | let mutability = if raw_tok { |
426 | if e.mut_token().is_some() { | ||
427 | Mutability::Mut | ||
428 | } else if e.const_token().is_some() { | ||
429 | Mutability::Shared | ||
430 | } else { | ||
431 | unreachable!("parser only remaps to raw_token() if matching mutability token follows") | ||
432 | } | ||
433 | } else { | ||
434 | Mutability::from_mutable(e.mut_token().is_some()) | ||
435 | }; | ||
436 | let rawness = Rawness::from_raw(raw_tok); | ||
437 | |||
438 | self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr) | ||
383 | } | 439 | } |
384 | ast::Expr::PrefixExpr(e) => { | 440 | ast::Expr::PrefixExpr(e) => { |
385 | let expr = self.collect_expr_opt(e.expr()); | 441 | let expr = self.collect_expr_opt(e.expr()); |
@@ -516,7 +572,8 @@ impl ExprCollector<'_> { | |||
516 | }) | 572 | }) |
517 | .collect(); | 573 | .collect(); |
518 | let tail = block.expr().map(|e| self.collect_expr(e)); | 574 | let tail = block.expr().map(|e| self.collect_expr(e)); |
519 | self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) | 575 | let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t)); |
576 | self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr) | ||
520 | } | 577 | } |
521 | 578 | ||
522 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { | 579 | fn collect_block_items(&mut self, block: &ast::BlockExpr) { |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 09e92b74e..e48ff38f9 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -138,10 +138,10 @@ fn compute_block_scopes( | |||
138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { | 138 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { |
139 | scopes.set_scope(expr, scope); | 139 | scopes.set_scope(expr, scope); |
140 | match &body[expr] { | 140 | match &body[expr] { |
141 | Expr::Block { statements, tail } => { | 141 | Expr::Block { statements, tail, .. } => { |
142 | compute_block_scopes(&statements, *tail, body, scopes, scope); | 142 | compute_block_scopes(&statements, *tail, body, scopes, scope); |
143 | } | 143 | } |
144 | Expr::For { iterable, pat, body: body_expr } => { | 144 | Expr::For { iterable, pat, body: body_expr, .. } => { |
145 | compute_expr_scopes(*iterable, body, scopes, scope); | 145 | compute_expr_scopes(*iterable, body, scopes, scope); |
146 | let scope = scopes.new_scope(scope); | 146 | let scope = scopes.new_scope(scope); |
147 | scopes.add_bindings(body, scope, *pat); | 147 | scopes.add_bindings(body, scope, *pat); |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index e2130d931..807195d25 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -34,6 +34,7 @@ pub struct FunctionData { | |||
34 | /// True if the first param is `self`. This is relevant to decide whether this | 34 | /// True if the first param is `self`. This is relevant to decide whether this |
35 | /// can be called as a method. | 35 | /// can be called as a method. |
36 | pub has_self_param: bool, | 36 | pub has_self_param: bool, |
37 | pub is_unsafe: bool, | ||
37 | pub visibility: RawVisibility, | 38 | pub visibility: RawVisibility, |
38 | } | 39 | } |
39 | 40 | ||
@@ -85,11 +86,14 @@ impl FunctionData { | |||
85 | ret_type | 86 | ret_type |
86 | }; | 87 | }; |
87 | 88 | ||
89 | let is_unsafe = src.value.unsafe_token().is_some(); | ||
90 | |||
88 | let vis_default = RawVisibility::default_for_container(loc.container); | 91 | let vis_default = RawVisibility::default_for_container(loc.container); |
89 | let visibility = | 92 | let visibility = |
90 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); | 93 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); |
91 | 94 | ||
92 | let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; | 95 | let sig = |
96 | FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs }; | ||
93 | Arc::new(sig) | 97 | Arc::new(sig) |
94 | } | 98 | } |
95 | } | 99 | } |
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index b221ae1ce..2630b3d89 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs | |||
@@ -29,6 +29,13 @@ impl Documentation { | |||
29 | Documentation(s.into()) | 29 | Documentation(s.into()) |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn from_ast<N>(node: &N) -> Option<Documentation> | ||
33 | where | ||
34 | N: ast::DocCommentsOwner + ast::AttrsOwner, | ||
35 | { | ||
36 | docs_from_ast(node) | ||
37 | } | ||
38 | |||
32 | pub fn as_str(&self) -> &str { | 39 | pub fn as_str(&self) -> &str { |
33 | &*self.0 | 40 | &*self.0 |
34 | } | 41 | } |
@@ -70,6 +77,45 @@ impl Documentation { | |||
70 | } | 77 | } |
71 | } | 78 | } |
72 | 79 | ||
73 | pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> { | 80 | pub(crate) fn docs_from_ast<N>(node: &N) -> Option<Documentation> |
74 | node.doc_comment_text().map(|it| Documentation::new(&it)) | 81 | where |
82 | N: ast::DocCommentsOwner + ast::AttrsOwner, | ||
83 | { | ||
84 | let doc_comment_text = node.doc_comment_text(); | ||
85 | let doc_attr_text = expand_doc_attrs(node); | ||
86 | let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text); | ||
87 | docs.map(|it| Documentation::new(&it)) | ||
88 | } | ||
89 | |||
90 | fn merge_doc_comments_and_attrs( | ||
91 | doc_comment_text: Option<String>, | ||
92 | doc_attr_text: Option<String>, | ||
93 | ) -> Option<String> { | ||
94 | match (doc_comment_text, doc_attr_text) { | ||
95 | (Some(mut comment_text), Some(attr_text)) => { | ||
96 | comment_text.push_str("\n\n"); | ||
97 | comment_text.push_str(&attr_text); | ||
98 | Some(comment_text) | ||
99 | } | ||
100 | (Some(comment_text), None) => Some(comment_text), | ||
101 | (None, Some(attr_text)) => Some(attr_text), | ||
102 | (None, None) => None, | ||
103 | } | ||
104 | } | ||
105 | |||
106 | fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> { | ||
107 | let mut docs = String::new(); | ||
108 | for attr in owner.attrs() { | ||
109 | if let Some(("doc", value)) = | ||
110 | attr.as_simple_key_value().as_ref().map(|(k, v)| (k.as_str(), v.as_str())) | ||
111 | { | ||
112 | docs.push_str(value); | ||
113 | docs.push_str("\n\n"); | ||
114 | } | ||
115 | } | ||
116 | if docs.is_empty() { | ||
117 | None | ||
118 | } else { | ||
119 | Some(docs.trim_end_matches("\n\n").to_owned()) | ||
120 | } | ||
75 | } | 121 | } |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index a0cdad529..ca49b26d1 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -19,7 +19,7 @@ use ra_syntax::ast::RangeOp; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | builtin_type::{BuiltinFloat, BuiltinInt}, | 20 | builtin_type::{BuiltinFloat, BuiltinInt}, |
21 | path::{GenericArgs, Path}, | 21 | path::{GenericArgs, Path}, |
22 | type_ref::{Mutability, TypeRef}, | 22 | type_ref::{Mutability, Rawness, TypeRef}, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | pub type ExprId = Idx<Expr>; | 25 | pub type ExprId = Idx<Expr>; |
@@ -52,18 +52,22 @@ pub enum Expr { | |||
52 | Block { | 52 | Block { |
53 | statements: Vec<Statement>, | 53 | statements: Vec<Statement>, |
54 | tail: Option<ExprId>, | 54 | tail: Option<ExprId>, |
55 | label: Option<Name>, | ||
55 | }, | 56 | }, |
56 | Loop { | 57 | Loop { |
57 | body: ExprId, | 58 | body: ExprId, |
59 | label: Option<Name>, | ||
58 | }, | 60 | }, |
59 | While { | 61 | While { |
60 | condition: ExprId, | 62 | condition: ExprId, |
61 | body: ExprId, | 63 | body: ExprId, |
64 | label: Option<Name>, | ||
62 | }, | 65 | }, |
63 | For { | 66 | For { |
64 | iterable: ExprId, | 67 | iterable: ExprId, |
65 | pat: PatId, | 68 | pat: PatId, |
66 | body: ExprId, | 69 | body: ExprId, |
70 | label: Option<Name>, | ||
67 | }, | 71 | }, |
68 | Call { | 72 | Call { |
69 | callee: ExprId, | 73 | callee: ExprId, |
@@ -79,9 +83,12 @@ pub enum Expr { | |||
79 | expr: ExprId, | 83 | expr: ExprId, |
80 | arms: Vec<MatchArm>, | 84 | arms: Vec<MatchArm>, |
81 | }, | 85 | }, |
82 | Continue, | 86 | Continue { |
87 | label: Option<Name>, | ||
88 | }, | ||
83 | Break { | 89 | Break { |
84 | expr: Option<ExprId>, | 90 | expr: Option<ExprId>, |
91 | label: Option<Name>, | ||
85 | }, | 92 | }, |
86 | Return { | 93 | Return { |
87 | expr: Option<ExprId>, | 94 | expr: Option<ExprId>, |
@@ -110,6 +117,7 @@ pub enum Expr { | |||
110 | }, | 117 | }, |
111 | Ref { | 118 | Ref { |
112 | expr: ExprId, | 119 | expr: ExprId, |
120 | rawness: Rawness, | ||
113 | mutability: Mutability, | 121 | mutability: Mutability, |
114 | }, | 122 | }, |
115 | Box { | 123 | Box { |
@@ -224,7 +232,7 @@ impl Expr { | |||
224 | f(*else_branch); | 232 | f(*else_branch); |
225 | } | 233 | } |
226 | } | 234 | } |
227 | Expr::Block { statements, tail } => { | 235 | Expr::Block { statements, tail, .. } => { |
228 | for stmt in statements { | 236 | for stmt in statements { |
229 | match stmt { | 237 | match stmt { |
230 | Statement::Let { initializer, .. } => { | 238 | Statement::Let { initializer, .. } => { |
@@ -240,8 +248,8 @@ impl Expr { | |||
240 | } | 248 | } |
241 | } | 249 | } |
242 | Expr::TryBlock { body } => f(*body), | 250 | Expr::TryBlock { body } => f(*body), |
243 | Expr::Loop { body } => f(*body), | 251 | Expr::Loop { body, .. } => f(*body), |
244 | Expr::While { condition, body } => { | 252 | Expr::While { condition, body, .. } => { |
245 | f(*condition); | 253 | f(*condition); |
246 | f(*body); | 254 | f(*body); |
247 | } | 255 | } |
@@ -267,8 +275,8 @@ impl Expr { | |||
267 | f(arm.expr); | 275 | f(arm.expr); |
268 | } | 276 | } |
269 | } | 277 | } |
270 | Expr::Continue => {} | 278 | Expr::Continue { .. } => {} |
271 | Expr::Break { expr } | Expr::Return { expr } => { | 279 | Expr::Break { expr, .. } | Expr::Return { expr } => { |
272 | if let Some(expr) = expr { | 280 | if let Some(expr) = expr { |
273 | f(*expr); | 281 | f(*expr); |
274 | } | 282 | } |
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index d962db3cc..3516784b8 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs | |||
@@ -164,7 +164,7 @@ impl LangItems { | |||
164 | T: Into<AttrDefId> + Copy, | 164 | T: Into<AttrDefId> + Copy, |
165 | { | 165 | { |
166 | if let Some(lang_item_name) = lang_attr(db, item) { | 166 | if let Some(lang_item_name) = lang_attr(db, item) { |
167 | self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item)); | 167 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); |
168 | } | 168 | } |
169 | } | 169 | } |
170 | } | 170 | } |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 4e628b14d..f44baa579 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -175,7 +175,7 @@ pub(super) enum DefKind { | |||
175 | } | 175 | } |
176 | 176 | ||
177 | impl DefKind { | 177 | impl DefKind { |
178 | pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { | 178 | pub fn ast_id(self) -> FileAstId<ast::ModuleItem> { |
179 | match self { | 179 | match self { |
180 | DefKind::Function(it) => it.upcast(), | 180 | DefKind::Function(it) => it.upcast(), |
181 | DefKind::Struct(it, _) => it.upcast(), | 181 | DefKind::Struct(it, _) => it.upcast(), |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 5bdad9efd..86a77b704 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -35,6 +35,22 @@ impl Mutability { | |||
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
39 | pub enum Rawness { | ||
40 | RawPtr, | ||
41 | Ref, | ||
42 | } | ||
43 | |||
44 | impl Rawness { | ||
45 | pub fn from_raw(is_raw: bool) -> Rawness { | ||
46 | if is_raw { | ||
47 | Rawness::RawPtr | ||
48 | } else { | ||
49 | Rawness::Ref | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
38 | /// Compare ty::Ty | 54 | /// Compare ty::Ty |
39 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 55 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
40 | pub enum TypeRef { | 56 | pub enum TypeRef { |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index fecce224e..660bdfe33 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -37,6 +37,11 @@ impl Name { | |||
37 | Name(Repr::TupleField(idx)) | 37 | Name(Repr::TupleField(idx)) |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn new_lifetime(lt: &ra_syntax::SyntaxToken) -> Name { | ||
41 | assert!(lt.kind() == ra_syntax::SyntaxKind::LIFETIME); | ||
42 | Name(Repr::Text(lt.text().clone())) | ||
43 | } | ||
44 | |||
40 | /// Shortcut to create inline plain text name | 45 | /// Shortcut to create inline plain text name |
41 | const fn new_inline_ascii(text: &[u8]) -> Name { | 46 | const fn new_inline_ascii(text: &[u8]) -> Name { |
42 | Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) | 47 | Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) |
@@ -148,6 +153,7 @@ pub mod known { | |||
148 | str, | 153 | str, |
149 | // Special names | 154 | // Special names |
150 | macro_rules, | 155 | macro_rules, |
156 | doc, | ||
151 | // Components of known path (value or mod name) | 157 | // Components of known path (value or mod name) |
152 | std, | 158 | std, |
153 | core, | 159 | core, |
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs index 4e0e069c8..04c026004 100644 --- a/crates/ra_hir_expand/src/proc_macro.rs +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -25,7 +25,7 @@ impl ProcMacroExpander { | |||
25 | } | 25 | } |
26 | 26 | ||
27 | pub fn expand( | 27 | pub fn expand( |
28 | &self, | 28 | self, |
29 | db: &dyn AstDatabase, | 29 | db: &dyn AstDatabase, |
30 | _id: LazyMacroId, | 30 | _id: LazyMacroId, |
31 | tt: &tt::Subtree, | 31 | tt: &tt::Subtree, |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index b2de7fa34..4b8dcdc07 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -27,9 +27,8 @@ test_utils = { path = "../test_utils" } | |||
27 | 27 | ||
28 | scoped-tls = "1" | 28 | scoped-tls = "1" |
29 | 29 | ||
30 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" } | 30 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" } |
31 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" } | 31 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" } |
32 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" } | ||
33 | 32 | ||
34 | [dev-dependencies] | 33 | [dev-dependencies] |
35 | insta = "0.16.0" | 34 | insta = "0.16.0" |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index dfc6c7dd6..0a8bb24ac 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -76,6 +76,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
76 | #[salsa::interned] | 76 | #[salsa::interned] |
77 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; | 77 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; |
78 | #[salsa::interned] | 78 | #[salsa::interned] |
79 | fn intern_callable_def(&self, callable_def: CallableDef) -> crate::CallableDefId; | ||
80 | #[salsa::interned] | ||
79 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; | 81 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; |
80 | #[salsa::interned] | 82 | #[salsa::interned] |
81 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; | 83 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; |
@@ -94,6 +96,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
94 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] | 96 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] |
95 | fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; | 97 | fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; |
96 | 98 | ||
99 | #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] | ||
100 | fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>; | ||
101 | |||
97 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] | 102 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] |
98 | fn associated_ty_value( | 103 | fn associated_ty_value( |
99 | &self, | 104 | &self, |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 41ac70272..2c7298714 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -40,7 +40,7 @@ impl Diagnostic for MissingFields { | |||
40 | fn message(&self) -> String { | 40 | fn message(&self) -> String { |
41 | let mut buf = String::from("Missing structure fields:\n"); | 41 | let mut buf = String::from("Missing structure fields:\n"); |
42 | for field in &self.missed_fields { | 42 | for field in &self.missed_fields { |
43 | format_to!(buf, "- {}", field); | 43 | format_to!(buf, "- {}\n", field); |
44 | } | 44 | } |
45 | buf | 45 | buf |
46 | } | 46 | } |
@@ -73,7 +73,7 @@ impl Diagnostic for MissingPatFields { | |||
73 | fn message(&self) -> String { | 73 | fn message(&self) -> String { |
74 | let mut buf = String::from("Missing structure fields:\n"); | 74 | let mut buf = String::from("Missing structure fields:\n"); |
75 | for field in &self.missed_fields { | 75 | for field in &self.missed_fields { |
76 | format_to!(buf, "- {}", field); | 76 | format_to!(buf, "- {}\n", field); |
77 | } | 77 | } |
78 | buf | 78 | buf |
79 | } | 79 | } |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 957d6e0b5..dc77e88e5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -219,6 +219,17 @@ struct InferenceContext<'a> { | |||
219 | struct BreakableContext { | 219 | struct BreakableContext { |
220 | pub may_break: bool, | 220 | pub may_break: bool, |
221 | pub break_ty: Ty, | 221 | pub break_ty: Ty, |
222 | pub label: Option<name::Name>, | ||
223 | } | ||
224 | |||
225 | fn find_breakable<'c>( | ||
226 | ctxs: &'c mut [BreakableContext], | ||
227 | label: Option<&name::Name>, | ||
228 | ) -> Option<&'c mut BreakableContext> { | ||
229 | match label { | ||
230 | Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label), | ||
231 | None => ctxs.last_mut(), | ||
232 | } | ||
222 | } | 233 | } |
223 | 234 | ||
224 | impl<'a> InferenceContext<'a> { | 235 | impl<'a> InferenceContext<'a> { |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 2ee9adb16..32c7c57cd 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -45,9 +45,7 @@ impl<'a> InferenceContext<'a> { | |||
45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
46 | } else { | 46 | } else { |
47 | mark::hit!(coerce_merge_fail_fallback); | 47 | mark::hit!(coerce_merge_fail_fallback); |
48 | // For incompatible types, we use the latter one as result | 48 | ty1.clone() |
49 | // to be better recovery for `if` without `else`. | ||
50 | ty2.clone() | ||
51 | } | 49 | } |
52 | } | 50 | } |
53 | } | 51 | } |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index b28724f0e..4a98e2deb 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -17,13 +17,13 @@ use crate::{ | |||
17 | autoderef, method_resolution, op, | 17 | autoderef, method_resolution, op, |
18 | traits::InEnvironment, | 18 | traits::InEnvironment, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, | 20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, |
21 | Ty, TypeCtor, Uncertain, | 21 | TraitRef, Ty, TypeCtor, Uncertain, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | use super::{ | 24 | use super::{ |
25 | BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, | 25 | find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, |
26 | TypeMismatch, | 26 | InferenceDiagnostic, TypeMismatch, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | impl<'a> InferenceContext<'a> { | 29 | impl<'a> InferenceContext<'a> { |
@@ -86,16 +86,20 @@ impl<'a> InferenceContext<'a> { | |||
86 | 86 | ||
87 | self.coerce_merge_branch(&then_ty, &else_ty) | 87 | self.coerce_merge_branch(&then_ty, &else_ty) |
88 | } | 88 | } |
89 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 89 | Expr::Block { statements, tail, .. } => { |
90 | // FIXME: Breakable block inference | ||
91 | self.infer_block(statements, *tail, expected) | ||
92 | } | ||
90 | Expr::TryBlock { body } => { | 93 | Expr::TryBlock { body } => { |
91 | let _inner = self.infer_expr(*body, expected); | 94 | let _inner = self.infer_expr(*body, expected); |
92 | // FIXME should be std::result::Result<{inner}, _> | 95 | // FIXME should be std::result::Result<{inner}, _> |
93 | Ty::Unknown | 96 | Ty::Unknown |
94 | } | 97 | } |
95 | Expr::Loop { body } => { | 98 | Expr::Loop { body, label } => { |
96 | self.breakables.push(BreakableContext { | 99 | self.breakables.push(BreakableContext { |
97 | may_break: false, | 100 | may_break: false, |
98 | break_ty: self.table.new_type_var(), | 101 | break_ty: self.table.new_type_var(), |
102 | label: label.clone(), | ||
99 | }); | 103 | }); |
100 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 104 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
101 | 105 | ||
@@ -110,8 +114,12 @@ impl<'a> InferenceContext<'a> { | |||
110 | Ty::simple(TypeCtor::Never) | 114 | Ty::simple(TypeCtor::Never) |
111 | } | 115 | } |
112 | } | 116 | } |
113 | Expr::While { condition, body } => { | 117 | Expr::While { condition, body, label } => { |
114 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); | 118 | self.breakables.push(BreakableContext { |
119 | may_break: false, | ||
120 | break_ty: Ty::Unknown, | ||
121 | label: label.clone(), | ||
122 | }); | ||
115 | // while let is desugared to a match loop, so this is always simple while | 123 | // while let is desugared to a match loop, so this is always simple while |
116 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 124 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
117 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 125 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
@@ -120,10 +128,14 @@ impl<'a> InferenceContext<'a> { | |||
120 | self.diverges = Diverges::Maybe; | 128 | self.diverges = Diverges::Maybe; |
121 | Ty::unit() | 129 | Ty::unit() |
122 | } | 130 | } |
123 | Expr::For { iterable, body, pat } => { | 131 | Expr::For { iterable, body, pat, label } => { |
124 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 132 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
125 | 133 | ||
126 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); | 134 | self.breakables.push(BreakableContext { |
135 | may_break: false, | ||
136 | break_ty: Ty::Unknown, | ||
137 | label: label.clone(), | ||
138 | }); | ||
127 | let pat_ty = | 139 | let pat_ty = |
128 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); | 140 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); |
129 | 141 | ||
@@ -140,13 +152,13 @@ impl<'a> InferenceContext<'a> { | |||
140 | 152 | ||
141 | let mut sig_tys = Vec::new(); | 153 | let mut sig_tys = Vec::new(); |
142 | 154 | ||
143 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { | 155 | // collect explicitly written argument types |
144 | let expected = if let Some(type_ref) = arg_type { | 156 | for arg_type in arg_types.iter() { |
157 | let arg_ty = if let Some(type_ref) = arg_type { | ||
145 | self.make_ty(type_ref) | 158 | self.make_ty(type_ref) |
146 | } else { | 159 | } else { |
147 | Ty::Unknown | 160 | self.table.new_type_var() |
148 | }; | 161 | }; |
149 | let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); | ||
150 | sig_tys.push(arg_ty); | 162 | sig_tys.push(arg_ty); |
151 | } | 163 | } |
152 | 164 | ||
@@ -158,7 +170,7 @@ impl<'a> InferenceContext<'a> { | |||
158 | sig_tys.push(ret_ty.clone()); | 170 | sig_tys.push(ret_ty.clone()); |
159 | let sig_ty = Ty::apply( | 171 | let sig_ty = Ty::apply( |
160 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | 172 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, |
161 | Substs(sig_tys.into()), | 173 | Substs(sig_tys.clone().into()), |
162 | ); | 174 | ); |
163 | let closure_ty = | 175 | let closure_ty = |
164 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); | 176 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); |
@@ -168,6 +180,12 @@ impl<'a> InferenceContext<'a> { | |||
168 | // infer the body. | 180 | // infer the body. |
169 | self.coerce(&closure_ty, &expected.ty); | 181 | self.coerce(&closure_ty, &expected.ty); |
170 | 182 | ||
183 | // Now go through the argument patterns | ||
184 | for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { | ||
185 | let resolved = self.resolve_ty_as_possible(arg_ty); | ||
186 | self.infer_pat(*arg_pat, &resolved, BindingMode::default()); | ||
187 | } | ||
188 | |||
171 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | 189 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
172 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); | 190 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); |
173 | 191 | ||
@@ -230,23 +248,24 @@ impl<'a> InferenceContext<'a> { | |||
230 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 248 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
231 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 249 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
232 | } | 250 | } |
233 | Expr::Continue => Ty::simple(TypeCtor::Never), | 251 | Expr::Continue { .. } => Ty::simple(TypeCtor::Never), |
234 | Expr::Break { expr } => { | 252 | Expr::Break { expr, label } => { |
235 | let val_ty = if let Some(expr) = expr { | 253 | let val_ty = if let Some(expr) = expr { |
236 | self.infer_expr(*expr, &Expectation::none()) | 254 | self.infer_expr(*expr, &Expectation::none()) |
237 | } else { | 255 | } else { |
238 | Ty::unit() | 256 | Ty::unit() |
239 | }; | 257 | }; |
240 | 258 | ||
241 | let last_ty = if let Some(ctxt) = self.breakables.last() { | 259 | let last_ty = |
242 | ctxt.break_ty.clone() | 260 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
243 | } else { | 261 | ctxt.break_ty.clone() |
244 | Ty::Unknown | 262 | } else { |
245 | }; | 263 | Ty::Unknown |
264 | }; | ||
246 | 265 | ||
247 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | 266 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); |
248 | 267 | ||
249 | if let Some(ctxt) = self.breakables.last_mut() { | 268 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
250 | ctxt.break_ty = merged_type; | 269 | ctxt.break_ty = merged_type; |
251 | ctxt.may_break = true; | 270 | ctxt.may_break = true; |
252 | } else { | 271 | } else { |
@@ -350,19 +369,28 @@ impl<'a> InferenceContext<'a> { | |||
350 | // FIXME check the cast... | 369 | // FIXME check the cast... |
351 | cast_ty | 370 | cast_ty |
352 | } | 371 | } |
353 | Expr::Ref { expr, mutability } => { | 372 | Expr::Ref { expr, rawness, mutability } => { |
354 | let expectation = | 373 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = |
355 | if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { | 374 | &expected.ty.as_reference_or_ptr() |
356 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 375 | { |
357 | // FIXME: throw type error - expected mut reference but found shared ref, | 376 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { |
358 | // which cannot be coerced | 377 | // FIXME: throw type error - expected mut reference but found shared ref, |
359 | } | 378 | // which cannot be coerced |
360 | Expectation::rvalue_hint(Ty::clone(exp_inner)) | 379 | } |
361 | } else { | 380 | if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr { |
362 | Expectation::none() | 381 | // FIXME: throw type error - expected reference but found ptr, |
363 | }; | 382 | // which cannot be coerced |
383 | } | ||
384 | Expectation::rvalue_hint(Ty::clone(exp_inner)) | ||
385 | } else { | ||
386 | Expectation::none() | ||
387 | }; | ||
364 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 388 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
365 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 389 | let ty = match rawness { |
390 | Rawness::RawPtr => TypeCtor::RawPtr(*mutability), | ||
391 | Rawness::Ref => TypeCtor::Ref(*mutability), | ||
392 | }; | ||
393 | Ty::apply_one(ty, inner_ty) | ||
366 | } | 394 | } |
367 | Expr::Box { expr } => { | 395 | Expr::Box { expr } => { |
368 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 396 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index e91c9be04..9fa8d3bdc 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -49,8 +49,10 @@ use std::sync::Arc; | |||
49 | use std::{iter, mem}; | 49 | use std::{iter, mem}; |
50 | 50 | ||
51 | use hir_def::{ | 51 | use hir_def::{ |
52 | expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, | 52 | expr::ExprId, |
53 | HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, | 53 | type_ref::{Mutability, Rawness}, |
54 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, | ||
55 | TypeParamId, | ||
54 | }; | 56 | }; |
55 | use ra_db::{impl_intern_key, salsa, CrateId}; | 57 | use ra_db::{impl_intern_key, salsa, CrateId}; |
56 | 58 | ||
@@ -159,6 +161,12 @@ pub enum TypeCtor { | |||
159 | pub struct TypeCtorId(salsa::InternId); | 161 | pub struct TypeCtorId(salsa::InternId); |
160 | impl_intern_key!(TypeCtorId); | 162 | impl_intern_key!(TypeCtorId); |
161 | 163 | ||
164 | /// This exists just for Chalk, because Chalk just has a single `FnDefId` where | ||
165 | /// we have different IDs for struct and enum variant constructors. | ||
166 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
167 | pub struct CallableDefId(salsa::InternId); | ||
168 | impl_intern_key!(CallableDefId); | ||
169 | |||
162 | impl TypeCtor { | 170 | impl TypeCtor { |
163 | pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { | 171 | pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { |
164 | match self { | 172 | match self { |
@@ -703,6 +711,18 @@ impl Ty { | |||
703 | } | 711 | } |
704 | } | 712 | } |
705 | 713 | ||
714 | pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { | ||
715 | match self { | ||
716 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | ||
717 | Some((parameters.as_single(), Rawness::Ref, *mutability)) | ||
718 | } | ||
719 | Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => { | ||
720 | Some((parameters.as_single(), Rawness::RawPtr, *mutability)) | ||
721 | } | ||
722 | _ => None, | ||
723 | } | ||
724 | } | ||
725 | |||
706 | pub fn strip_references(&self) -> &Ty { | 726 | pub fn strip_references(&self) -> &Ty { |
707 | let mut t: &Ty = self; | 727 | let mut t: &Ty = self; |
708 | 728 | ||
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 2cc4f4bf9..6f777ed8c 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -116,15 +116,20 @@ fn infer_let_stmt_coerce() { | |||
116 | assert_snapshot!( | 116 | assert_snapshot!( |
117 | infer(r#" | 117 | infer(r#" |
118 | fn test() { | 118 | fn test() { |
119 | let x: &[i32] = &[1]; | 119 | let x: &[isize] = &[1]; |
120 | let x: *const [isize] = &[1]; | ||
120 | } | 121 | } |
121 | "#), | 122 | "#), |
122 | @r###" | 123 | @r###" |
123 | 11..40 '{ ...[1]; }': () | 124 | 11..76 '{ ...[1]; }': () |
124 | 21..22 'x': &[i32] | 125 | 21..22 'x': &[isize] |
125 | 33..37 '&[1]': &[i32; _] | 126 | 35..39 '&[1]': &[isize; _] |
126 | 34..37 '[1]': [i32; _] | 127 | 36..39 '[1]': [isize; _] |
127 | 35..36 '1': i32 | 128 | 37..38 '1': isize |
129 | 49..50 'x': *const [isize] | ||
130 | 69..73 '&[1]': &[isize; _] | ||
131 | 70..73 '[1]': [isize; _] | ||
132 | 71..72 '1': isize | ||
128 | "###); | 133 | "###); |
129 | } | 134 | } |
130 | 135 | ||
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 0c5f972a2..fe62587c0 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -520,3 +520,53 @@ fn main() { | |||
520 | 105..107 '()': () | 520 | 105..107 '()': () |
521 | ") | 521 | ") |
522 | } | 522 | } |
523 | |||
524 | #[test] | ||
525 | fn match_ergonomics_in_closure_params() { | ||
526 | assert_snapshot!( | ||
527 | infer(r#" | ||
528 | #[lang = "fn_once"] | ||
529 | trait FnOnce<Args> { | ||
530 | type Output; | ||
531 | } | ||
532 | |||
533 | fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} } | ||
534 | |||
535 | fn test() { | ||
536 | foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics | ||
537 | foo(&(1, "a"), |(x, y)| x); | ||
538 | } | ||
539 | "#), | ||
540 | @r###" | ||
541 | 94..95 't': T | ||
542 | 100..101 'f': F | ||
543 | 111..122 '{ loop {} }': U | ||
544 | 113..120 'loop {}': ! | ||
545 | 118..120 '{}': () | ||
546 | 134..233 '{ ... x); }': () | ||
547 | 140..143 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32 | ||
548 | 140..167 'foo(&(...y)| x)': i32 | ||
549 | 144..153 '&(1, "a")': &(i32, &str) | ||
550 | 145..153 '(1, "a")': (i32, &str) | ||
551 | 146..147 '1': i32 | ||
552 | 149..152 '"a"': &str | ||
553 | 155..166 '|&(x, y)| x': |&(i32, &str)| -> i32 | ||
554 | 156..163 '&(x, y)': &(i32, &str) | ||
555 | 157..163 '(x, y)': (i32, &str) | ||
556 | 158..159 'x': i32 | ||
557 | 161..162 'y': &str | ||
558 | 165..166 'x': i32 | ||
559 | 204..207 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32 | ||
560 | 204..230 'foo(&(...y)| x)': &i32 | ||
561 | 208..217 '&(1, "a")': &(i32, &str) | ||
562 | 209..217 '(1, "a")': (i32, &str) | ||
563 | 210..211 '1': i32 | ||
564 | 213..216 '"a"': &str | ||
565 | 219..229 '|(x, y)| x': |&(i32, &str)| -> &i32 | ||
566 | 220..226 '(x, y)': (i32, &str) | ||
567 | 221..222 'x': &i32 | ||
568 | 224..225 'y': &&str | ||
569 | 228..229 'x': &i32 | ||
570 | "### | ||
571 | ); | ||
572 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index fd2208af2..88309157b 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -385,6 +385,26 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { | |||
385 | } | 385 | } |
386 | 386 | ||
387 | #[test] | 387 | #[test] |
388 | fn infer_raw_ref() { | ||
389 | assert_snapshot!( | ||
390 | infer(r#" | ||
391 | fn test(a: i32) { | ||
392 | &raw mut a; | ||
393 | &raw const a; | ||
394 | } | ||
395 | "#), | ||
396 | @r###" | ||
397 | 9..10 'a': i32 | ||
398 | 17..54 '{ ...t a; }': () | ||
399 | 23..33 '&raw mut a': *mut i32 | ||
400 | 32..33 'a': i32 | ||
401 | 39..51 '&raw const a': *const i32 | ||
402 | 50..51 'a': i32 | ||
403 | "### | ||
404 | ); | ||
405 | } | ||
406 | |||
407 | #[test] | ||
388 | fn infer_literals() { | 408 | fn infer_literals() { |
389 | assert_snapshot!( | 409 | assert_snapshot!( |
390 | infer(r##" | 410 | infer(r##" |
@@ -937,7 +957,7 @@ fn main(foo: Foo) { | |||
937 | 51..107 'if tru... }': () | 957 | 51..107 'if tru... }': () |
938 | 54..58 'true': bool | 958 | 54..58 'true': bool |
939 | 59..67 '{ }': () | 959 | 59..67 '{ }': () |
940 | 73..107 'if fal... }': () | 960 | 73..107 'if fal... }': i32 |
941 | 76..81 'false': bool | 961 | 76..81 'false': bool |
942 | 82..107 '{ ... }': i32 | 962 | 82..107 '{ ... }': i32 |
943 | 92..95 'foo': Foo | 963 | 92..95 'foo': Foo |
@@ -1923,3 +1943,57 @@ fn test() { | |||
1923 | "### | 1943 | "### |
1924 | ); | 1944 | ); |
1925 | } | 1945 | } |
1946 | |||
1947 | #[test] | ||
1948 | fn infer_labelled_break_with_val() { | ||
1949 | assert_snapshot!( | ||
1950 | infer(r#" | ||
1951 | fn foo() { | ||
1952 | let _x = || 'outer: loop { | ||
1953 | let inner = 'inner: loop { | ||
1954 | let i = Default::default(); | ||
1955 | if (break 'outer i) { | ||
1956 | loop { break 'inner 5i8; }; | ||
1957 | } else if true { | ||
1958 | break 'inner 6; | ||
1959 | } | ||
1960 | break 7; | ||
1961 | }; | ||
1962 | break inner < 8; | ||
1963 | }; | ||
1964 | } | ||
1965 | "#), | ||
1966 | @r###" | ||
1967 | 10..336 '{ ... }; }': () | ||
1968 | 20..22 '_x': || -> bool | ||
1969 | 25..333 '|| 'ou... }': || -> bool | ||
1970 | 28..333 ''outer... }': bool | ||
1971 | 41..333 '{ ... }': () | ||
1972 | 55..60 'inner': i8 | ||
1973 | 63..301 ''inner... }': i8 | ||
1974 | 76..301 '{ ... }': () | ||
1975 | 94..95 'i': bool | ||
1976 | 98..114 'Defaul...efault': {unknown} | ||
1977 | 98..116 'Defaul...ault()': bool | ||
1978 | 130..270 'if (br... }': () | ||
1979 | 134..148 'break 'outer i': ! | ||
1980 | 147..148 'i': bool | ||
1981 | 150..209 '{ ... }': () | ||
1982 | 168..194 'loop {...5i8; }': ! | ||
1983 | 173..194 '{ brea...5i8; }': () | ||
1984 | 175..191 'break ...er 5i8': ! | ||
1985 | 188..191 '5i8': i8 | ||
1986 | 215..270 'if tru... }': () | ||
1987 | 218..222 'true': bool | ||
1988 | 223..270 '{ ... }': () | ||
1989 | 241..255 'break 'inner 6': ! | ||
1990 | 254..255 '6': i8 | ||
1991 | 283..290 'break 7': ! | ||
1992 | 289..290 '7': i8 | ||
1993 | 311..326 'break inner < 8': ! | ||
1994 | 317..322 'inner': i8 | ||
1995 | 317..326 'inner < 8': bool | ||
1996 | 325..326 '8': i8 | ||
1997 | "### | ||
1998 | ); | ||
1999 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 6826610cb..e8778d419 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -2644,6 +2644,79 @@ fn test() { | |||
2644 | } | 2644 | } |
2645 | 2645 | ||
2646 | #[test] | 2646 | #[test] |
2647 | fn builtin_fn_def_copy() { | ||
2648 | assert_snapshot!( | ||
2649 | infer_with_mismatches(r#" | ||
2650 | #[lang = "copy"] | ||
2651 | trait Copy {} | ||
2652 | |||
2653 | fn foo() {} | ||
2654 | fn bar<T: Copy>(T) -> T {} | ||
2655 | struct Struct(usize); | ||
2656 | enum Enum { Variant(usize) } | ||
2657 | |||
2658 | trait Test { fn test(&self) -> bool; } | ||
2659 | impl<T: Copy> Test for T {} | ||
2660 | |||
2661 | fn test() { | ||
2662 | foo.test(); | ||
2663 | bar.test(); | ||
2664 | Struct.test(); | ||
2665 | Enum::Variant.test(); | ||
2666 | } | ||
2667 | "#, true), | ||
2668 | @r###" | ||
2669 | 42..44 '{}': () | ||
2670 | 61..62 'T': {unknown} | ||
2671 | 69..71 '{}': () | ||
2672 | 69..71: expected T, got () | ||
2673 | 146..150 'self': &Self | ||
2674 | 202..282 '{ ...t(); }': () | ||
2675 | 208..211 'foo': fn foo() | ||
2676 | 208..218 'foo.test()': bool | ||
2677 | 224..227 'bar': fn bar<{unknown}>({unknown}) -> {unknown} | ||
2678 | 224..234 'bar.test()': bool | ||
2679 | 240..246 'Struct': Struct(usize) -> Struct | ||
2680 | 240..253 'Struct.test()': bool | ||
2681 | 259..272 'Enum::Variant': Variant(usize) -> Enum | ||
2682 | 259..279 'Enum::...test()': bool | ||
2683 | "### | ||
2684 | ); | ||
2685 | } | ||
2686 | |||
2687 | #[test] | ||
2688 | fn builtin_fn_ptr_copy() { | ||
2689 | assert_snapshot!( | ||
2690 | infer_with_mismatches(r#" | ||
2691 | #[lang = "copy"] | ||
2692 | trait Copy {} | ||
2693 | |||
2694 | trait Test { fn test(&self) -> bool; } | ||
2695 | impl<T: Copy> Test for T {} | ||
2696 | |||
2697 | fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { | ||
2698 | f1.test(); | ||
2699 | f2.test(); | ||
2700 | f3.test(); | ||
2701 | } | ||
2702 | "#, true), | ||
2703 | @r###" | ||
2704 | 55..59 'self': &Self | ||
2705 | 109..111 'f1': fn() | ||
2706 | 119..121 'f2': fn(usize) -> u8 | ||
2707 | 140..142 'f3': fn(u8, u8) -> &u8 | ||
2708 | 163..211 '{ ...t(); }': () | ||
2709 | 169..171 'f1': fn() | ||
2710 | 169..178 'f1.test()': bool | ||
2711 | 184..186 'f2': fn(usize) -> u8 | ||
2712 | 184..193 'f2.test()': bool | ||
2713 | 199..201 'f3': fn(u8, u8) -> &u8 | ||
2714 | 199..208 'f3.test()': bool | ||
2715 | "### | ||
2716 | ); | ||
2717 | } | ||
2718 | |||
2719 | #[test] | ||
2647 | fn builtin_sized() { | 2720 | fn builtin_sized() { |
2648 | assert_snapshot!( | 2721 | assert_snapshot!( |
2649 | infer_with_mismatches(r#" | 2722 | infer_with_mismatches(r#" |
@@ -2680,3 +2753,48 @@ fn test() { | |||
2680 | "### | 2753 | "### |
2681 | ); | 2754 | ); |
2682 | } | 2755 | } |
2756 | |||
2757 | #[test] | ||
2758 | fn integer_range_iterate() { | ||
2759 | let t = type_at( | ||
2760 | r#" | ||
2761 | //- /main.rs crate:main deps:std | ||
2762 | fn test() { | ||
2763 | for x in 0..100 { x<|>; } | ||
2764 | } | ||
2765 | |||
2766 | //- /std.rs crate:std | ||
2767 | pub mod ops { | ||
2768 | pub struct Range<Idx> { | ||
2769 | pub start: Idx, | ||
2770 | pub end: Idx, | ||
2771 | } | ||
2772 | } | ||
2773 | |||
2774 | pub mod iter { | ||
2775 | pub trait Iterator { | ||
2776 | type Item; | ||
2777 | } | ||
2778 | |||
2779 | pub trait IntoIterator { | ||
2780 | type Item; | ||
2781 | type IntoIter: Iterator<Item = Self::Item>; | ||
2782 | } | ||
2783 | |||
2784 | impl<T> IntoIterator for T where T: Iterator { | ||
2785 | type Item = <T as Iterator>::Item; | ||
2786 | type IntoIter = Self; | ||
2787 | } | ||
2788 | } | ||
2789 | |||
2790 | trait Step {} | ||
2791 | impl Step for i32 {} | ||
2792 | impl Step for i64 {} | ||
2793 | |||
2794 | impl<A: Step> iter::Iterator for ops::Range<A> { | ||
2795 | type Item = A; | ||
2796 | } | ||
2797 | "#, | ||
2798 | ); | ||
2799 | assert_eq!(t, "i32"); | ||
2800 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index ccab246bf..88a422d2c 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs | |||
@@ -290,8 +290,7 @@ fn trait_object_unsize_impl_datum( | |||
290 | let self_trait_ref = TraitRef { trait_, substs: self_substs }; | 290 | let self_trait_ref = TraitRef { trait_, substs: self_substs }; |
291 | let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; | 291 | let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; |
292 | 292 | ||
293 | let impl_substs = | 293 | let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build(); |
294 | Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.clone().into())).build(); | ||
295 | 294 | ||
296 | let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; | 295 | let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; |
297 | 296 | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index e2f2a9ccb..61de3cc30 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -4,6 +4,7 @@ use std::sync::Arc; | |||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; | 6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; |
7 | use chalk_solve::rust_ir::{self, WellKnownTrait}; | ||
7 | 8 | ||
8 | use hir_def::{ | 9 | use hir_def::{ |
9 | lang_item::{lang_attr, LangItemTarget}, | 10 | lang_item::{lang_attr, LangItemTarget}, |
@@ -14,9 +15,8 @@ use ra_db::{salsa::InternKey, CrateId}; | |||
14 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; | 15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
15 | use crate::{ | 16 | use crate::{ |
16 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 17 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, |
17 | DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, | 18 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
18 | }; | 19 | }; |
19 | use chalk_rust_ir::WellKnownTrait; | ||
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | 20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; |
21 | 21 | ||
22 | pub use self::interner::*; | 22 | pub use self::interner::*; |
@@ -54,10 +54,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
54 | 54 | ||
55 | fn fn_def_datum( | 55 | fn fn_def_datum( |
56 | &self, | 56 | &self, |
57 | _fn_def_id: chalk_ir::FnDefId<Interner>, | 57 | fn_def_id: chalk_ir::FnDefId<Interner>, |
58 | ) -> Arc<chalk_rust_ir::FnDefDatum<Interner>> { | 58 | ) -> Arc<rust_ir::FnDefDatum<Interner>> { |
59 | // We don't yet provide any FnDefs to Chalk | 59 | self.db.fn_def_datum(self.krate, fn_def_id) |
60 | unimplemented!() | ||
61 | } | 60 | } |
62 | 61 | ||
63 | fn impls_for_trait( | 62 | fn impls_for_trait( |
@@ -113,7 +112,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
113 | } | 112 | } |
114 | fn well_known_trait_id( | 113 | fn well_known_trait_id( |
115 | &self, | 114 | &self, |
116 | well_known_trait: chalk_rust_ir::WellKnownTrait, | 115 | well_known_trait: rust_ir::WellKnownTrait, |
117 | ) -> Option<chalk_ir::TraitId<Interner>> { | 116 | ) -> Option<chalk_ir::TraitId<Interner>> { |
118 | let lang_attr = lang_attr_from_well_known_trait(well_known_trait); | 117 | let lang_attr = lang_attr_from_well_known_trait(well_known_trait); |
119 | let lang_items = self.db.crate_lang_items(self.krate); | 118 | let lang_items = self.db.crate_lang_items(self.krate); |
@@ -134,13 +133,13 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
134 | fn opaque_ty_data( | 133 | fn opaque_ty_data( |
135 | &self, | 134 | &self, |
136 | _id: chalk_ir::OpaqueTyId<Interner>, | 135 | _id: chalk_ir::OpaqueTyId<Interner>, |
137 | ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { | 136 | ) -> Arc<rust_ir::OpaqueTyDatum<Interner>> { |
138 | unimplemented!() | 137 | unimplemented!() |
139 | } | 138 | } |
140 | 139 | ||
141 | fn force_impl_for( | 140 | fn force_impl_for( |
142 | &self, | 141 | &self, |
143 | _well_known: chalk_rust_ir::WellKnownTrait, | 142 | _well_known: rust_ir::WellKnownTrait, |
144 | _ty: &chalk_ir::TyData<Interner>, | 143 | _ty: &chalk_ir::TyData<Interner>, |
145 | ) -> Option<bool> { | 144 | ) -> Option<bool> { |
146 | // this method is mostly for rustc | 145 | // this method is mostly for rustc |
@@ -151,6 +150,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
151 | // FIXME: implement actual object safety | 150 | // FIXME: implement actual object safety |
152 | true | 151 | true |
153 | } | 152 | } |
153 | |||
154 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { | ||
155 | Ty::Unknown.to_chalk(self.db) | ||
156 | } | ||
154 | } | 157 | } |
155 | 158 | ||
156 | pub(crate) fn program_clauses_for_chalk_env_query( | 159 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -189,7 +192,7 @@ pub(crate) fn associated_ty_data_query( | |||
189 | .collect(); | 192 | .collect(); |
190 | 193 | ||
191 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | 194 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); |
192 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; | 195 | let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; |
193 | let datum = AssociatedTyDatum { | 196 | let datum = AssociatedTyDatum { |
194 | trait_id: trait_.to_chalk(db), | 197 | trait_id: trait_.to_chalk(db), |
195 | id, | 198 | id, |
@@ -210,7 +213,7 @@ pub(crate) fn trait_datum_query( | |||
210 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); | 213 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); |
211 | let generic_params = generics(db.upcast(), trait_.into()); | 214 | let generic_params = generics(db.upcast(), trait_.into()); |
212 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 215 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
213 | let flags = chalk_rust_ir::TraitFlags { | 216 | let flags = rust_ir::TraitFlags { |
214 | auto: trait_data.auto, | 217 | auto: trait_data.auto, |
215 | upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, | 218 | upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, |
216 | non_enumerable: true, | 219 | non_enumerable: true, |
@@ -222,7 +225,7 @@ pub(crate) fn trait_datum_query( | |||
222 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | 225 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); |
223 | let associated_ty_ids = | 226 | let associated_ty_ids = |
224 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); | 227 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); |
225 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; | 228 | let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; |
226 | let well_known = | 229 | let well_known = |
227 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); | 230 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); |
228 | let trait_datum = TraitDatum { | 231 | let trait_datum = TraitDatum { |
@@ -272,12 +275,12 @@ pub(crate) fn struct_datum_query( | |||
272 | convert_where_clauses(db, generic_def, &bound_vars) | 275 | convert_where_clauses(db, generic_def, &bound_vars) |
273 | }) | 276 | }) |
274 | .unwrap_or_else(Vec::new); | 277 | .unwrap_or_else(Vec::new); |
275 | let flags = chalk_rust_ir::AdtFlags { | 278 | let flags = rust_ir::AdtFlags { |
276 | upstream, | 279 | upstream, |
277 | // FIXME set fundamental flag correctly | 280 | // FIXME set fundamental flag correctly |
278 | fundamental: false, | 281 | fundamental: false, |
279 | }; | 282 | }; |
280 | let struct_datum_bound = chalk_rust_ir::AdtDatumBound { | 283 | let struct_datum_bound = rust_ir::AdtDatumBound { |
281 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 284 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
282 | where_clauses, | 285 | where_clauses, |
283 | }; | 286 | }; |
@@ -317,9 +320,9 @@ fn impl_def_datum( | |||
317 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 320 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
318 | let trait_ = trait_ref.trait_; | 321 | let trait_ = trait_ref.trait_; |
319 | let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { | 322 | let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { |
320 | chalk_rust_ir::ImplType::Local | 323 | rust_ir::ImplType::Local |
321 | } else { | 324 | } else { |
322 | chalk_rust_ir::ImplType::External | 325 | rust_ir::ImplType::External |
323 | }; | 326 | }; |
324 | let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars); | 327 | let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars); |
325 | let negative = impl_data.is_negative; | 328 | let negative = impl_data.is_negative; |
@@ -332,13 +335,9 @@ fn impl_def_datum( | |||
332 | ); | 335 | ); |
333 | let trait_ref = trait_ref.to_chalk(db); | 336 | let trait_ref = trait_ref.to_chalk(db); |
334 | 337 | ||
335 | let polarity = if negative { | 338 | let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; |
336 | chalk_rust_ir::Polarity::Negative | ||
337 | } else { | ||
338 | chalk_rust_ir::Polarity::Positive | ||
339 | }; | ||
340 | 339 | ||
341 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; | 340 | let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; |
342 | let trait_data = db.trait_data(trait_); | 341 | let trait_data = db.trait_data(trait_); |
343 | let associated_ty_value_ids = impl_data | 342 | let associated_ty_value_ids = impl_data |
344 | .items | 343 | .items |
@@ -396,8 +395,8 @@ fn type_alias_associated_ty_value( | |||
396 | .associated_type_by_name(&type_alias_data.name) | 395 | .associated_type_by_name(&type_alias_data.name) |
397 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | 396 | .expect("assoc ty value should not exist"); // validated when building the impl data as well |
398 | let ty = db.ty(type_alias.into()); | 397 | let ty = db.ty(type_alias.into()); |
399 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; | 398 | let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; |
400 | let value = chalk_rust_ir::AssociatedTyValue { | 399 | let value = rust_ir::AssociatedTyValue { |
401 | impl_id: Impl::ImplDef(impl_id).to_chalk(db), | 400 | impl_id: Impl::ImplDef(impl_id).to_chalk(db), |
402 | associated_ty_id: assoc_ty.to_chalk(db), | 401 | associated_ty_id: assoc_ty.to_chalk(db), |
403 | value: make_binders(value_bound, ty.num_binders), | 402 | value: make_binders(value_bound, ty.num_binders), |
@@ -405,6 +404,26 @@ fn type_alias_associated_ty_value( | |||
405 | Arc::new(value) | 404 | Arc::new(value) |
406 | } | 405 | } |
407 | 406 | ||
407 | pub(crate) fn fn_def_datum_query( | ||
408 | db: &dyn HirDatabase, | ||
409 | _krate: CrateId, | ||
410 | fn_def_id: FnDefId, | ||
411 | ) -> Arc<FnDefDatum> { | ||
412 | let callable_def: CallableDef = from_chalk(db, fn_def_id); | ||
413 | let generic_params = generics(db.upcast(), callable_def.into()); | ||
414 | let sig = db.callable_item_signature(callable_def); | ||
415 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | ||
416 | let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); | ||
417 | let bound = rust_ir::FnDefDatumBound { | ||
418 | // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway | ||
419 | argument_types: sig.value.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), | ||
420 | return_type: sig.value.ret().clone().to_chalk(db), | ||
421 | where_clauses, | ||
422 | }; | ||
423 | let datum = FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders) }; | ||
424 | Arc::new(datum) | ||
425 | } | ||
426 | |||
408 | impl From<AdtId> for crate::TypeCtorId { | 427 | impl From<AdtId> for crate::TypeCtorId { |
409 | fn from(struct_id: AdtId) -> Self { | 428 | fn from(struct_id: AdtId) -> Self { |
410 | struct_id.0 | 429 | struct_id.0 |
@@ -417,6 +436,18 @@ impl From<crate::TypeCtorId> for AdtId { | |||
417 | } | 436 | } |
418 | } | 437 | } |
419 | 438 | ||
439 | impl From<FnDefId> for crate::CallableDefId { | ||
440 | fn from(fn_def_id: FnDefId) -> Self { | ||
441 | InternKey::from_intern_id(fn_def_id.0) | ||
442 | } | ||
443 | } | ||
444 | |||
445 | impl From<crate::CallableDefId> for FnDefId { | ||
446 | fn from(callable_def_id: crate::CallableDefId) -> Self { | ||
447 | chalk_ir::FnDefId(callable_def_id.as_intern_id()) | ||
448 | } | ||
449 | } | ||
450 | |||
420 | impl From<ImplId> for crate::traits::GlobalImplId { | 451 | impl From<ImplId> for crate::traits::GlobalImplId { |
421 | fn from(impl_id: ImplId) -> Self { | 452 | fn from(impl_id: ImplId) -> Self { |
422 | InternKey::from_intern_id(impl_id.0) | 453 | InternKey::from_intern_id(impl_id.0) |
@@ -429,14 +460,14 @@ impl From<crate::traits::GlobalImplId> for ImplId { | |||
429 | } | 460 | } |
430 | } | 461 | } |
431 | 462 | ||
432 | impl From<chalk_rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { | 463 | impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { |
433 | fn from(id: chalk_rust_ir::AssociatedTyValueId<Interner>) -> Self { | 464 | fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { |
434 | Self::from_intern_id(id.0) | 465 | Self::from_intern_id(id.0) |
435 | } | 466 | } |
436 | } | 467 | } |
437 | 468 | ||
438 | impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId<Interner> { | 469 | impl From<crate::traits::AssocTyValueId> for rust_ir::AssociatedTyValueId<Interner> { |
439 | fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { | 470 | fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { |
440 | chalk_rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id()) | 471 | rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id()) |
441 | } | 472 | } |
442 | } | 473 | } |
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs index 060372819..e27074ba6 100644 --- a/crates/ra_hir_ty/src/traits/chalk/interner.rs +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -11,15 +11,17 @@ use std::{fmt, sync::Arc}; | |||
11 | pub struct Interner; | 11 | pub struct Interner; |
12 | 12 | ||
13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | 13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
14 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; | 14 | pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; |
15 | pub type TraitId = chalk_ir::TraitId<Interner>; | 15 | pub type TraitId = chalk_ir::TraitId<Interner>; |
16 | pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; | 16 | pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; |
17 | pub type AdtId = chalk_ir::AdtId<Interner>; | 17 | pub type AdtId = chalk_ir::AdtId<Interner>; |
18 | pub type StructDatum = chalk_rust_ir::AdtDatum<Interner>; | 18 | pub type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; |
19 | pub type ImplId = chalk_ir::ImplId<Interner>; | 19 | pub type ImplId = chalk_ir::ImplId<Interner>; |
20 | pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; | 20 | pub type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; |
21 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; | 21 | pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; |
22 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; | 22 | pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; |
23 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | ||
24 | pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; | ||
23 | 25 | ||
24 | impl chalk_ir::interner::Interner for Interner { | 26 | impl chalk_ir::interner::Interner for Interner { |
25 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? | 27 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? |
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index a83d82fd8..5f6daf842 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -7,6 +7,7 @@ use chalk_ir::{ | |||
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, | 7 | cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, |
8 | UniverseIndex, | 8 | UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_solve::rust_ir; | ||
10 | 11 | ||
11 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 12 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; |
12 | use ra_db::salsa::InternKey; | 13 | use ra_db::salsa::InternKey; |
@@ -15,8 +16,8 @@ use crate::{ | |||
15 | db::HirDatabase, | 16 | db::HirDatabase, |
16 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, |