diff options
-rw-r--r-- | Cargo.lock | 81 | ||||
-rw-r--r-- | crates/ra_assists/src/assist_ctx.rs | 2 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 131 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_ty/Cargo.toml | 7 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 35 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 74 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 468 | ||||
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 4 | ||||
-rw-r--r-- | docs/user/assists.md | 22 | ||||
-rw-r--r-- | xtask/src/main.rs | 2 |
20 files changed, 634 insertions, 357 deletions
diff --git a/Cargo.lock b/Cargo.lock index 55afcda7b..792e30494 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -66,6 +66,11 @@ dependencies = [ | |||
66 | ] | 66 | ] |
67 | 67 | ||
68 | [[package]] | 68 | [[package]] |
69 | name = "base64" | ||
70 | version = "0.11.0" | ||
71 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
72 | |||
73 | [[package]] | ||
69 | name = "bit-set" | 74 | name = "bit-set" |
70 | version = "0.5.1" | 75 | version = "0.5.1" |
71 | source = "registry+https://github.com/rust-lang/crates.io-index" | 76 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -128,7 +133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
128 | [[package]] | 133 | [[package]] |
129 | name = "chalk-derive" | 134 | name = "chalk-derive" |
130 | version = "0.1.0" | 135 | version = "0.1.0" |
131 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 136 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
132 | dependencies = [ | 137 | dependencies = [ |
133 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | 138 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", |
134 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | 139 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -138,27 +143,27 @@ dependencies = [ | |||
138 | [[package]] | 143 | [[package]] |
139 | name = "chalk-engine" | 144 | name = "chalk-engine" |
140 | version = "0.9.0" | 145 | version = "0.9.0" |
141 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 146 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
142 | dependencies = [ | 147 | dependencies = [ |
143 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 148 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
144 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 149 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
145 | ] | 150 | ] |
146 | 151 | ||
147 | [[package]] | 152 | [[package]] |
148 | name = "chalk-ir" | 153 | name = "chalk-ir" |
149 | version = "0.1.0" | 154 | version = "0.1.0" |
150 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 155 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
151 | dependencies = [ | 156 | dependencies = [ |
152 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 157 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
153 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 158 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
154 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 159 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
155 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", | 160 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", |
156 | ] | 161 | ] |
157 | 162 | ||
158 | [[package]] | 163 | [[package]] |
159 | name = "chalk-macros" | 164 | name = "chalk-macros" |
160 | version = "0.1.1" | 165 | version = "0.1.1" |
161 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 166 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
162 | dependencies = [ | 167 | dependencies = [ |
163 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 168 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
164 | ] | 169 | ] |
@@ -166,24 +171,24 @@ dependencies = [ | |||
166 | [[package]] | 171 | [[package]] |
167 | name = "chalk-rust-ir" | 172 | name = "chalk-rust-ir" |
168 | version = "0.1.0" | 173 | version = "0.1.0" |
169 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 174 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
170 | dependencies = [ | 175 | dependencies = [ |
171 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 176 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
172 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 177 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
173 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 178 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
174 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 179 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
175 | ] | 180 | ] |
176 | 181 | ||
177 | [[package]] | 182 | [[package]] |
178 | name = "chalk-solve" | 183 | name = "chalk-solve" |
179 | version = "0.1.0" | 184 | version = "0.1.0" |
180 | source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" | 185 | source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" |
181 | dependencies = [ | 186 | dependencies = [ |
182 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 187 | "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
183 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 188 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
184 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 189 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
185 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 190 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
186 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 191 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
187 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", | 192 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", |
188 | "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", | 193 | "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", |
189 | "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", | 194 | "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -620,9 +625,10 @@ dependencies = [ | |||
620 | 625 | ||
621 | [[package]] | 626 | [[package]] |
622 | name = "lsp-types" | 627 | name = "lsp-types" |
623 | version = "0.65.0" | 628 | version = "0.67.1" |
624 | source = "registry+https://github.com/rust-lang/crates.io-index" | 629 | source = "registry+https://github.com/rust-lang/crates.io-index" |
625 | dependencies = [ | 630 | dependencies = [ |
631 | "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
626 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | 632 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", |
627 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", | 633 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", |
628 | "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", | 634 | "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -995,9 +1001,9 @@ name = "ra_hir_ty" | |||
995 | version = "0.1.0" | 1001 | version = "0.1.0" |
996 | dependencies = [ | 1002 | dependencies = [ |
997 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1003 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", |
998 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 1004 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
999 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 1005 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
1000 | "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", | 1006 | "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", |
1001 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1007 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1002 | "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1008 | "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1003 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1009 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1034,7 +1040,7 @@ dependencies = [ | |||
1034 | "ra_syntax 0.1.0", | 1040 | "ra_syntax 0.1.0", |
1035 | "ra_text_edit 0.1.0", | 1041 | "ra_text_edit 0.1.0", |
1036 | "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1042 | "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1037 | "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1043 | "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1038 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1044 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1039 | "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1045 | "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1040 | "test_utils 0.1.0", | 1046 | "test_utils 0.1.0", |
@@ -1050,7 +1056,7 @@ dependencies = [ | |||
1050 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1056 | "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1051 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", | 1057 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", |
1052 | "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1058 | "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1053 | "lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1059 | "lsp-types 0.67.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1054 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1060 | "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1055 | "ra_ide 0.1.0", | 1061 | "ra_ide 0.1.0", |
1056 | "ra_prof 0.1.0", | 1062 | "ra_prof 0.1.0", |
@@ -1314,17 +1320,17 @@ dependencies = [ | |||
1314 | 1320 | ||
1315 | [[package]] | 1321 | [[package]] |
1316 | name = "rayon" | 1322 | name = "rayon" |
1317 | version = "1.2.1" | 1323 | version = "1.3.0" |
1318 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1319 | dependencies = [ | 1325 | dependencies = [ |
1320 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1326 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", |
1321 | "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", | 1327 | "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", |
1322 | "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1328 | "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1323 | ] | 1329 | ] |
1324 | 1330 | ||
1325 | [[package]] | 1331 | [[package]] |
1326 | name = "rayon-core" | 1332 | name = "rayon-core" |
1327 | version = "1.6.1" | 1333 | version = "1.7.0" |
1328 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1329 | dependencies = [ | 1335 | dependencies = [ |
1330 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | 1336 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1773,6 +1779,7 @@ dependencies = [ | |||
1773 | "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" | 1779 | "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" |
1774 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" | 1780 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" |
1775 | "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" | 1781 | "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" |
1782 | "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" | ||
1776 | "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" | 1783 | "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" |
1777 | "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" | 1784 | "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" |
1778 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | 1785 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" |
@@ -1782,12 +1789,12 @@ dependencies = [ | |||
1782 | "checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" | 1789 | "checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" |
1783 | "checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" | 1790 | "checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" |
1784 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | 1791 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" |
1785 | "checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1792 | "checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1786 | "checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1793 | "checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1787 | "checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1794 | "checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1788 | "checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1795 | "checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1789 | "checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1796 | "checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1790 | "checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "<none>" | 1797 | "checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "<none>" |
1791 | "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" | 1798 | "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" |
1792 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" | 1799 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" |
1793 | "checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" | 1800 | "checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" |
@@ -1842,7 +1849,7 @@ dependencies = [ | |||
1842 | "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" | 1849 | "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" |
1843 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" | 1850 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" |
1844 | "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" | 1851 | "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" |
1845 | "checksum lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fe9e427e63e6172699737b47f1044bcade7046e2404d59ebd90c459da47cd2b" | 1852 | "checksum lsp-types 0.67.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aea9639ebf210bd5de66931cbdb2d4a8bcc1fa1e5b2dece7daa6b387ab42e803" |
1846 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" | 1853 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" |
1847 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" | 1854 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" |
1848 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" | 1855 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" |
@@ -1884,8 +1891,8 @@ dependencies = [ | |||
1884 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" | 1891 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" |
1885 | "checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" | 1892 | "checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" |
1886 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" | 1893 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" |
1887 | "checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" | 1894 | "checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" |
1888 | "checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" | 1895 | "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" |
1889 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" | 1896 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" |
1890 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" | 1897 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" |
1891 | "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" | 1898 | "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" |
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 993aebc47..28152f724 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -46,7 +46,7 @@ pub(crate) enum Assist { | |||
46 | /// | 46 | /// |
47 | /// Note, however, that we don't actually use such two-phase logic at the | 47 | /// Note, however, that we don't actually use such two-phase logic at the |
48 | /// moment, because the LSP API is pretty awkward in this place, and it's much | 48 | /// moment, because the LSP API is pretty awkward in this place, and it's much |
49 | /// easier to just compute the edit eagerly :-)#[derive(Debug, Clone)] | 49 | /// easier to just compute the edit eagerly :-) |
50 | #[derive(Debug)] | 50 | #[derive(Debug)] |
51 | pub(crate) struct AssistCtx<'a, DB> { | 51 | pub(crate) struct AssistCtx<'a, DB> { |
52 | pub(crate) db: &'a DB, | 52 | pub(crate) db: &'a DB, |
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index cef669cb5..bc49e71fe 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::collections::HashMap; | ||
2 | |||
1 | use hir::{db::HirDatabase, HasSource}; | 3 | use hir::{db::HirDatabase, HasSource}; |
2 | use ra_syntax::{ | 4 | use ra_syntax::{ |
3 | ast::{self, edit, make, AstNode, NameOwner}, | 5 | ast::{self, edit, make, AstNode, NameOwner}, |
@@ -17,26 +19,26 @@ enum AddMissingImplMembersMode { | |||
17 | // Adds scaffold for required impl members. | 19 | // Adds scaffold for required impl members. |
18 | // | 20 | // |
19 | // ``` | 21 | // ``` |
20 | // trait T { | 22 | // trait Trait<T> { |
21 | // Type X; | 23 | // Type X; |
22 | // fn foo(&self); | 24 | // fn foo(&self) -> T; |
23 | // fn bar(&self) {} | 25 | // fn bar(&self) {} |
24 | // } | 26 | // } |
25 | // | 27 | // |
26 | // impl T for () {<|> | 28 | // impl Trait<u32> for () {<|> |
27 | // | 29 | // |
28 | // } | 30 | // } |
29 | // ``` | 31 | // ``` |
30 | // -> | 32 | // -> |
31 | // ``` | 33 | // ``` |
32 | // trait T { | 34 | // trait Trait<T> { |
33 | // Type X; | 35 | // Type X; |
34 | // fn foo(&self); | 36 | // fn foo(&self) -> T; |
35 | // fn bar(&self) {} | 37 | // fn bar(&self) {} |
36 | // } | 38 | // } |
37 | // | 39 | // |
38 | // impl T for () { | 40 | // impl Trait<u32> for () { |
39 | // fn foo(&self) { unimplemented!() } | 41 | // fn foo(&self) -> u32 { unimplemented!() } |
40 | // | 42 | // |
41 | // } | 43 | // } |
42 | // ``` | 44 | // ``` |
@@ -54,13 +56,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti | |||
54 | // Adds scaffold for overriding default impl members. | 56 | // Adds scaffold for overriding default impl members. |
55 | // | 57 | // |
56 | // ``` | 58 | // ``` |
57 | // trait T { | 59 | // trait Trait { |
58 | // Type X; | 60 | // Type X; |
59 | // fn foo(&self); | 61 | // fn foo(&self); |
60 | // fn bar(&self) {} | 62 | // fn bar(&self) {} |
61 | // } | 63 | // } |
62 | // | 64 | // |
63 | // impl T for () { | 65 | // impl Trait for () { |
64 | // Type X = (); | 66 | // Type X = (); |
65 | // fn foo(&self) {}<|> | 67 | // fn foo(&self) {}<|> |
66 | // | 68 | // |
@@ -68,13 +70,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti | |||
68 | // ``` | 70 | // ``` |
69 | // -> | 71 | // -> |
70 | // ``` | 72 | // ``` |
71 | // trait T { | 73 | // trait Trait { |
72 | // Type X; | 74 | // Type X; |
73 | // fn foo(&self); | 75 | // fn foo(&self); |
74 | // fn bar(&self) {} | 76 | // fn bar(&self) {} |
75 | // } | 77 | // } |
76 | // | 78 | // |
77 | // impl T for () { | 79 | // impl Trait for () { |
78 | // Type X = (); | 80 | // Type X = (); |
79 | // fn foo(&self) {} | 81 | // fn foo(&self) {} |
80 | // fn bar(&self) {} | 82 | // fn bar(&self) {} |
@@ -99,7 +101,7 @@ fn add_missing_impl_members_inner( | |||
99 | let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; | 101 | let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; |
100 | let impl_item_list = impl_node.item_list()?; | 102 | let impl_item_list = impl_node.item_list()?; |
101 | 103 | ||
102 | let trait_def = { | 104 | let (trait_, trait_def) = { |
103 | let analyzer = ctx.source_analyzer(impl_node.syntax(), None); | 105 | let analyzer = ctx.source_analyzer(impl_node.syntax(), None); |
104 | 106 | ||
105 | resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? | 107 | resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? |
@@ -132,10 +134,25 @@ fn add_missing_impl_members_inner( | |||
132 | return None; | 134 | return None; |
133 | } | 135 | } |
134 | 136 | ||
137 | let file_id = ctx.frange.file_id; | ||
138 | let db = ctx.db; | ||
139 | |||
135 | ctx.add_assist(AssistId(assist_id), label, |edit| { | 140 | ctx.add_assist(AssistId(assist_id), label, |edit| { |
136 | let n_existing_items = impl_item_list.impl_items().count(); | 141 | let n_existing_items = impl_item_list.impl_items().count(); |
142 | let substs = get_syntactic_substs(impl_node).unwrap_or_default(); | ||
143 | let generic_def: hir::GenericDef = trait_.into(); | ||
144 | let substs_by_param: HashMap<_, _> = generic_def | ||
145 | .params(db) | ||
146 | .into_iter() | ||
147 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky | ||
148 | .skip(1) | ||
149 | .zip(substs.into_iter()) | ||
150 | .collect(); | ||
137 | let items = missing_items | 151 | let items = missing_items |
138 | .into_iter() | 152 | .into_iter() |
153 | .map(|it| { | ||
154 | substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) | ||
155 | }) | ||
139 | .map(|it| match it { | 156 | .map(|it| match it { |
140 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), | 157 | ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), |
141 | _ => it, | 158 | _ => it, |
@@ -160,13 +177,63 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | |||
160 | } | 177 | } |
161 | } | 178 | } |
162 | 179 | ||
180 | // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the | ||
181 | // trait ref, and then go from the types in the substs back to the syntax) | ||
182 | // FIXME: This should be a general utility (not even just for assists) | ||
183 | fn get_syntactic_substs(impl_block: ast::ImplBlock) -> Option<Vec<ast::TypeRef>> { | ||
184 | let target_trait = impl_block.target_trait()?; | ||
185 | let path_type = match target_trait { | ||
186 | ast::TypeRef::PathType(path) => path, | ||
187 | _ => return None, | ||
188 | }; | ||
189 | let type_arg_list = path_type.path()?.segment()?.type_arg_list()?; | ||
190 | let mut result = Vec::new(); | ||
191 | for type_arg in type_arg_list.type_args() { | ||
192 | let type_arg: ast::TypeArg = type_arg; | ||
193 | result.push(type_arg.type_ref()?); | ||
194 | } | ||
195 | Some(result) | ||
196 | } | ||
197 | |||
198 | // FIXME: This should be a general utility (not even just for assists) | ||
199 | fn substitute_type_params<N: AstNode>( | ||
200 | db: &impl HirDatabase, | ||
201 | node: hir::InFile<N>, | ||
202 | substs: &HashMap<hir::TypeParam, ast::TypeRef>, | ||
203 | ) -> N { | ||
204 | let type_param_replacements = node | ||
205 | .value | ||
206 | .syntax() | ||
207 | .descendants() | ||
208 | .filter_map(ast::TypeRef::cast) | ||
209 | .filter_map(|n| { | ||
210 | let path = match &n { | ||
211 | ast::TypeRef::PathType(path_type) => path_type.path()?, | ||
212 | _ => return None, | ||
213 | }; | ||
214 | let analyzer = hir::SourceAnalyzer::new(db, node.with_value(n.syntax()), None); | ||
215 | let resolution = analyzer.resolve_path(db, &path)?; | ||
216 | match resolution { | ||
217 | hir::PathResolution::TypeParam(tp) => Some((n, substs.get(&tp)?.clone())), | ||
218 | _ => None, | ||
219 | } | ||
220 | }) | ||
221 | .collect::<Vec<_>>(); | ||
222 | |||
223 | if type_param_replacements.is_empty() { | ||
224 | node.value | ||
225 | } else { | ||
226 | edit::replace_descendants(&node.value, type_param_replacements.into_iter()) | ||
227 | } | ||
228 | } | ||
229 | |||
163 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 230 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
164 | /// implemented) to a `ast::TraitDef`. | 231 | /// implemented) to a `ast::TraitDef`. |
165 | fn resolve_target_trait_def( | 232 | fn resolve_target_trait_def( |
166 | db: &impl HirDatabase, | 233 | db: &impl HirDatabase, |
167 | analyzer: &hir::SourceAnalyzer, | 234 | analyzer: &hir::SourceAnalyzer, |
168 | impl_block: &ast::ImplBlock, | 235 | impl_block: &ast::ImplBlock, |
169 | ) -> Option<ast::TraitDef> { | 236 | ) -> Option<(hir::Trait, ast::TraitDef)> { |
170 | let ast_path = impl_block | 237 | let ast_path = impl_block |
171 | .target_trait() | 238 | .target_trait() |
172 | .map(|it| it.syntax().clone()) | 239 | .map(|it| it.syntax().clone()) |
@@ -174,7 +241,9 @@ fn resolve_target_trait_def( | |||
174 | .path()?; | 241 | .path()?; |
175 | 242 | ||
176 | match analyzer.resolve_path(db, &ast_path) { | 243 | match analyzer.resolve_path(db, &ast_path) { |
177 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).value), | 244 | Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => { |
245 | Some((def, def.source(db).value)) | ||
246 | } | ||
178 | _ => None, | 247 | _ => None, |
179 | } | 248 | } |
180 | } | 249 | } |
@@ -281,6 +350,40 @@ impl Foo for S { | |||
281 | } | 350 | } |
282 | 351 | ||
283 | #[test] | 352 | #[test] |
353 | fn fill_in_type_params_1() { | ||
354 | check_assist( | ||
355 | add_missing_impl_members, | ||
356 | " | ||
357 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
358 | struct S; | ||
359 | impl Foo<u32> for S { <|> }", | ||
360 | " | ||
361 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
362 | struct S; | ||
363 | impl Foo<u32> for S { | ||
364 | <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() } | ||
365 | }", | ||
366 | ); | ||
367 | } | ||
368 | |||
369 | #[test] | ||
370 | fn fill_in_type_params_2() { | ||
371 | check_assist( | ||
372 | add_missing_impl_members, | ||
373 | " | ||
374 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
375 | struct S; | ||
376 | impl<U> Foo<U> for S { <|> }", | ||
377 | " | ||
378 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | ||
379 | struct S; | ||
380 | impl<U> Foo<U> for S { | ||
381 | <|>fn foo(&self, t: U) -> &U { unimplemented!() } | ||
382 | }", | ||
383 | ); | ||
384 | } | ||
385 | |||
386 | #[test] | ||
284 | fn test_cursor_after_empty_impl_block() { | 387 | fn test_cursor_after_empty_impl_block() { |
285 | check_assist( | 388 | check_assist( |
286 | add_missing_impl_members, | 389 | add_missing_impl_members, |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 4586eeb59..7d84dc8fb 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -101,26 +101,26 @@ fn doctest_add_impl_default_members() { | |||
101 | check( | 101 | check( |
102 | "add_impl_default_members", | 102 | "add_impl_default_members", |
103 | r#####" | 103 | r#####" |
104 | trait T { | 104 | trait Trait { |
105 | Type X; | 105 | Type X; |
106 | fn foo(&self); | 106 | fn foo(&self); |
107 | fn bar(&self) {} | 107 | fn bar(&self) {} |
108 | } | 108 | } |
109 | 109 | ||
110 | impl T for () { | 110 | impl Trait for () { |
111 | Type X = (); | 111 | Type X = (); |
112 | fn foo(&self) {}<|> | 112 | fn foo(&self) {}<|> |
113 | 113 | ||
114 | } | 114 | } |
115 | "#####, | 115 | "#####, |
116 | r#####" | 116 | r#####" |
117 | trait T { | 117 | trait Trait { |
118 | Type X; | 118 | Type X; |
119 | fn foo(&self); | 119 | fn foo(&self); |
120 | fn bar(&self) {} | 120 | fn bar(&self) {} |
121 | } | 121 | } |
122 | 122 | ||
123 | impl T for () { | 123 | impl Trait for () { |
124 | Type X = (); | 124 | Type X = (); |
125 | fn foo(&self) {} | 125 | fn foo(&self) {} |
126 | fn bar(&self) {} | 126 | fn bar(&self) {} |
@@ -135,25 +135,25 @@ fn doctest_add_impl_missing_members() { | |||
135 | check( | 135 | check( |
136 | "add_impl_missing_members", | 136 | "add_impl_missing_members", |
137 | r#####" | 137 | r#####" |
138 | trait T { | 138 | trait Trait<T> { |
139 | Type X; | 139 | Type X; |
140 | fn foo(&self); | 140 | fn foo(&self) -> T; |
141 | fn bar(&self) {} | 141 | fn bar(&self) {} |
142 | } | 142 | } |
143 | 143 | ||
144 | impl T for () {<|> | 144 | impl Trait<u32> for () {<|> |
145 | 145 | ||
146 | } | 146 | } |
147 | "#####, | 147 | "#####, |
148 | r#####" | 148 | r#####" |
149 | trait T { | 149 | trait Trait<T> { |
150 | Type X; | 150 | Type X; |
151 | fn foo(&self); | 151 | fn foo(&self) -> T; |
152 | fn bar(&self) {} | 152 | fn bar(&self) {} |
153 | } | 153 | } |
154 | 154 | ||
155 | impl T for () { | 155 | impl Trait<u32> for () { |
156 | fn foo(&self) { unimplemented!() } | 156 | fn foo(&self) -> u32 { unimplemented!() } |
157 | 157 | ||
158 | } | 158 | } |
159 | "#####, | 159 | "#####, |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index bcfc0d03e..76d8f85f1 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -644,6 +644,17 @@ impl_froms!( | |||
644 | Const | 644 | Const |
645 | ); | 645 | ); |
646 | 646 | ||
647 | impl GenericDef { | ||
648 | pub fn params(self, db: &impl HirDatabase) -> Vec<TypeParam> { | ||
649 | let generics: Arc<hir_def::generics::GenericParams> = db.generic_params(self.into()); | ||
650 | generics | ||
651 | .types | ||
652 | .iter() | ||
653 | .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) | ||
654 | .collect() | ||
655 | } | ||
656 | } | ||
657 | |||
647 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 658 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
648 | pub struct Local { | 659 | pub struct Local { |
649 | pub(crate) parent: DefWithBody, | 660 | pub(crate) parent: DefWithBody, |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 1aa9a9b7d..c900a6a18 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -10,8 +10,9 @@ use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAs | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::DefDatabase, | 12 | db::DefDatabase, |
13 | path::{path, GenericArgs, Path}, | ||
13 | src::HasSource, | 14 | src::HasSource, |
14 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeBound, TypeRef}, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, |
16 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 17 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
17 | }; | 18 | }; |
@@ -62,11 +63,29 @@ impl FunctionData { | |||
62 | TypeRef::unit() | 63 | TypeRef::unit() |
63 | }; | 64 | }; |
64 | 65 | ||
66 | let ret_type = if src.value.is_async() { | ||
67 | let future_impl = desugar_future_path(ret_type); | ||
68 | let ty_bound = TypeBound::Path(future_impl); | ||
69 | TypeRef::ImplTrait(vec![ty_bound]) | ||
70 | } else { | ||
71 | ret_type | ||
72 | }; | ||
73 | |||
65 | let sig = FunctionData { name, params, ret_type, has_self_param }; | 74 | let sig = FunctionData { name, params, ret_type, has_self_param }; |
66 | Arc::new(sig) | 75 | Arc::new(sig) |
67 | } | 76 | } |
68 | } | 77 | } |
69 | 78 | ||
79 | fn desugar_future_path(orig: TypeRef) -> Path { | ||
80 | let path = path![std::future::Future]; | ||
81 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | ||
82 | let mut last = GenericArgs::empty(); | ||
83 | last.bindings.push((name![Output], orig)); | ||
84 | generic_args.push(Some(Arc::new(last))); | ||
85 | |||
86 | Path::from_known_path(path, generic_args) | ||
87 | } | ||
88 | |||
70 | #[derive(Debug, Clone, PartialEq, Eq)] | 89 | #[derive(Debug, Clone, PartialEq, Eq)] |
71 | pub struct TypeAliasData { | 90 | pub struct TypeAliasData { |
72 | pub name: Name, | 91 | pub name: Name, |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 8e1294201..107d2d799 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -130,6 +130,14 @@ impl Path { | |||
130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } | 130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } |
131 | } | 131 | } |
132 | 132 | ||
133 | /// Converts a known mod path to `Path`. | ||
134 | pub(crate) fn from_known_path( | ||
135 | path: ModPath, | ||
136 | generic_args: Vec<Option<Arc<GenericArgs>>>, | ||
137 | ) -> Path { | ||
138 | Path { type_anchor: None, mod_path: path, generic_args } | ||
139 | } | ||
140 | |||
133 | pub fn kind(&self) -> &PathKind { | 141 | pub fn kind(&self) -> &PathKind { |
134 | &self.mod_path.kind | 142 | &self.mod_path.kind |
135 | } | 143 | } |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index d277bf2bc..60793db44 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -21,10 +21,9 @@ ra_prof = { path = "../ra_prof" } | |||
21 | ra_syntax = { path = "../ra_syntax" } | 21 | ra_syntax = { path = "../ra_syntax" } |
22 | test_utils = { path = "../test_utils" } | 22 | test_utils = { path = "../test_utils" } |
23 | 23 | ||
24 | # https://github.com/rust-lang/chalk/pull/294 | 24 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } |
25 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } | 25 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } |
26 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } | 26 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } |
27 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } | ||
28 | 27 | ||
29 | lalrpop-intern = "0.15.1" | 28 | lalrpop-intern = "0.15.1" |
30 | 29 | ||
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 222a36a9f..d52f65b83 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -10,7 +10,7 @@ use ra_db::{salsa, CrateId}; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | method_resolution::CrateImplBlocks, | 12 | method_resolution::CrateImplBlocks, |
13 | traits::{AssocTyValue, Impl}, | 13 | traits::{chalk, AssocTyValue, Impl}, |
14 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, | 14 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, |
15 | ValueTyDefId, | 15 | ValueTyDefId, |
16 | }; | 16 | }; |
@@ -77,39 +77,24 @@ pub trait HirDatabase: DefDatabase { | |||
77 | #[salsa::interned] | 77 | #[salsa::interned] |
78 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; | 78 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; |
79 | 79 | ||
80 | #[salsa::invoke(crate::traits::chalk::associated_ty_data_query)] | 80 | #[salsa::invoke(chalk::associated_ty_data_query)] |
81 | fn associated_ty_data( | 81 | fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; |
82 | &self, | ||
83 | id: chalk_ir::TypeId, | ||
84 | ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>; | ||
85 | 82 | ||
86 | #[salsa::invoke(crate::traits::chalk::trait_datum_query)] | 83 | #[salsa::invoke(chalk::trait_datum_query)] |
87 | fn trait_datum( | 84 | fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; |
88 | &self, | ||
89 | krate: CrateId, | ||
90 | trait_id: chalk_ir::TraitId, | ||
91 | ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>; | ||
92 | 85 | ||
93 | #[salsa::invoke(crate::traits::chalk::struct_datum_query)] | 86 | #[salsa::invoke(chalk::struct_datum_query)] |
94 | fn struct_datum( | 87 | fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc<chalk::StructDatum>; |
95 | &self, | ||
96 | krate: CrateId, | ||
97 | struct_id: chalk_ir::StructId, | ||
98 | ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>; | ||
99 | 88 | ||
100 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] | 89 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] |
101 | fn impl_datum( | 90 | fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; |
102 | &self, | ||
103 | krate: CrateId, | ||
104 | impl_id: chalk_ir::ImplId, | ||
105 | ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>; | ||
106 | 91 | ||
107 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] | 92 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] |
108 | fn associated_ty_value( | 93 | fn associated_ty_value( |
109 | &self, | 94 | &self, |
110 | krate: CrateId, | 95 | krate: CrateId, |
111 | id: chalk_rust_ir::AssociatedTyValueId, | 96 | id: chalk::AssociatedTyValueId, |
112 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>; | 97 | ) -> Arc<chalk::AssociatedTyValue>; |
113 | 98 | ||
114 | #[salsa::invoke(crate::traits::trait_solve_query)] | 99 | #[salsa::invoke(crate::traits::trait_solve_query)] |
115 | fn trait_solve( | 100 | fn trait_solve( |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index e97b81473..32c0d07a5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use test_utils::tested_by; | |||
37 | use super::{ | 37 | use super::{ |
38 | primitive::{FloatTy, IntTy}, | 38 | primitive::{FloatTy, IntTy}, |
39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
40 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | 40 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, |
41 | TypeWalk, Uncertain, | 41 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
42 | }; | 42 | }; |
43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; |
44 | 44 | ||
@@ -379,6 +379,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
379 | ) -> Ty { | 379 | ) -> Ty { |
380 | match assoc_ty { | 380 | match assoc_ty { |
381 | Some(res_assoc_ty) => { | 381 | Some(res_assoc_ty) => { |
382 | // FIXME: | ||
383 | // Check if inner_ty is is `impl Trait` and contained input TypeAlias id | ||
384 | // this is a workaround while Chalk assoc type projection doesn't always work yet, | ||
385 | // but once that is fixed I don't think we should keep this | ||
386 | // (we'll probably change how associated types are resolved anyway) | ||
387 | if let Ty::Opaque(ref predicates) = inner_ty { | ||
388 | for p in predicates.iter() { | ||
389 | if let GenericPredicate::Projection(projection) = p { | ||
390 | if projection.projection_ty.associated_ty == res_assoc_ty { | ||
391 | if let ty_app!(_, params) = &projection.ty { | ||
392 | if params.len() == 0 { | ||
393 | return projection.ty.clone(); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | |||
382 | let ty = self.table.new_type_var(); | 401 | let ty = self.table.new_type_var(); |
383 | let builder = Substs::build_for_def(self.db, res_assoc_ty) | 402 | let builder = Substs::build_for_def(self.db, res_assoc_ty) |
384 | .push(inner_ty) | 403 | .push(inner_ty) |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 45164c9e9..ce9a06fde 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -865,7 +865,7 @@ mod foo { | |||
865 | 865 | ||
866 | #[test] | 866 | #[test] |
867 | fn method_resolution_where_clause_for_unknown_trait() { | 867 | fn method_resolution_where_clause_for_unknown_trait() { |
868 | // The blanket impl shouldn't apply because we can't even resolve UnknownTrait | 868 | // The blanket impl currently applies because we ignore the unresolved where clause |
869 | let t = type_at( | 869 | let t = type_at( |
870 | r#" | 870 | r#" |
871 | //- /main.rs | 871 | //- /main.rs |
@@ -875,7 +875,7 @@ impl<T> Trait for T where T: UnknownTrait {} | |||
875 | fn test() { (&S).foo()<|>; } | 875 | fn test() { (&S).foo()<|>; } |
876 | "#, | 876 | "#, |
877 | ); | 877 | ); |
878 | assert_eq!(t, "{unknown}"); | 878 | assert_eq!(t, "u128"); |
879 | } | 879 | } |
880 | 880 | ||
881 | #[test] | 881 | #[test] |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 76e2198b6..0bc72644a 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -38,6 +38,63 @@ mod future { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | #[test] | 40 | #[test] |
41 | fn infer_async() { | ||
42 | let (db, pos) = TestDB::with_position( | ||
43 | r#" | ||
44 | //- /main.rs crate:main deps:std | ||
45 | |||
46 | async fn foo() -> u64 { | ||
47 | 128 | ||
48 | } | ||
49 | |||
50 | fn test() { | ||
51 | let r = foo(); | ||
52 | let v = r.await; | ||
53 | v<|>; | ||
54 | } | ||
55 | |||
56 | //- /std.rs crate:std | ||
57 | #[prelude_import] use future::*; | ||
58 | mod future { | ||
59 | trait Future { | ||
60 | type Output; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | "#, | ||
65 | ); | ||
66 | assert_eq!("u64", type_at_pos(&db, pos)); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
70 | fn infer_desugar_async() { | ||
71 | let (db, pos) = TestDB::with_position( | ||
72 | r#" | ||
73 | //- /main.rs crate:main deps:std | ||
74 | |||
75 | async fn foo() -> u64 { | ||
76 | 128 | ||
77 | } | ||
78 | |||
79 | fn test() { | ||
80 | let r = foo(); | ||
81 | r<|>; | ||
82 | } | ||
83 | |||
84 | //- /std.rs crate:std | ||
85 | #[prelude_import] use future::*; | ||
86 | mod future { | ||
87 | trait Future { | ||
88 | type Output; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | "#, | ||
93 | ); | ||
94 | assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos)); | ||
95 | } | ||
96 | |||
97 | #[test] | ||
41 | fn infer_try() { | 98 | fn infer_try() { |
42 | let (db, pos) = TestDB::with_position( | 99 | let (db, pos) = TestDB::with_position( |
43 | r#" | 100 | r#" |
@@ -959,6 +1016,23 @@ fn test() { | |||
959 | } | 1016 | } |
960 | 1017 | ||
961 | #[test] | 1018 | #[test] |
1019 | fn error_bound_chalk() { | ||
1020 | let t = type_at( | ||
1021 | r#" | ||
1022 | //- /main.rs | ||
1023 | trait Trait { | ||
1024 | fn foo(&self) -> u32 {} | ||
1025 | } | ||
1026 | |||
1027 | fn test(x: (impl Trait + UnknownTrait)) { | ||
1028 | x.foo()<|>; | ||
1029 | } | ||
1030 | "#, | ||
1031 | ); | ||
1032 | assert_eq!(t, "u32"); | ||
1033 | } | ||
1034 | |||
1035 | #[test] | ||
962 | fn assoc_type_bindings() { | 1036 | fn assoc_type_bindings() { |
963 | assert_snapshot!( | 1037 | assert_snapshot!( |
964 | infer(r#" | 1038 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index d49f8fb4b..c4dc857bc 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use chalk_ir::{cast::Cast, family::ChalkIr}; | 4 | use chalk_ir::cast::Cast; |
5 | use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; | 5 | use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; |
6 | use log::debug; | 6 | use log::debug; |
7 | use ra_db::{impl_intern_key, salsa, CrateId}; | 7 | use ra_db::{impl_intern_key, salsa, CrateId}; |
@@ -12,7 +12,7 @@ use crate::db::HirDatabase; | |||
12 | 12 | ||
13 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 13 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
14 | 14 | ||
15 | use self::chalk::{from_chalk, ToChalk}; | 15 | use self::chalk::{from_chalk, ToChalk, TypeFamily}; |
16 | 16 | ||
17 | pub(crate) mod chalk; | 17 | pub(crate) mod chalk; |
18 | mod builtin; | 18 | mod builtin; |
@@ -20,7 +20,7 @@ mod builtin; | |||
20 | #[derive(Debug, Clone)] | 20 | #[derive(Debug, Clone)] |
21 | pub struct TraitSolver { | 21 | pub struct TraitSolver { |
22 | krate: CrateId, | 22 | krate: CrateId, |
23 | inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, | 23 | inner: Arc<Mutex<chalk_solve::Solver<TypeFamily>>>, |
24 | } | 24 | } |
25 | 25 | ||
26 | /// We need eq for salsa | 26 | /// We need eq for salsa |
@@ -36,8 +36,8 @@ impl TraitSolver { | |||
36 | fn solve( | 36 | fn solve( |
37 | &self, | 37 | &self, |
38 | db: &impl HirDatabase, | 38 | db: &impl HirDatabase, |
39 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, | 39 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>, |
40 | ) -> Option<chalk_solve::Solution<ChalkIr>> { | 40 | ) -> Option<chalk_solve::Solution<TypeFamily>> { |
41 | let context = ChalkContext { db, krate: self.krate }; | 41 | let context = ChalkContext { db, krate: self.krate }; |
42 | debug!("solve goal: {:?}", goal); | 42 | debug!("solve goal: {:?}", goal); |
43 | let mut solver = match self.inner.lock() { | 43 | let mut solver = match self.inner.lock() { |
@@ -201,17 +201,17 @@ pub(crate) fn trait_solve_query( | |||
201 | 201 | ||
202 | fn solution_from_chalk( | 202 | fn solution_from_chalk( |
203 | db: &impl HirDatabase, | 203 | db: &impl HirDatabase, |
204 | solution: chalk_solve::Solution<ChalkIr>, | 204 | solution: chalk_solve::Solution<TypeFamily>, |
205 | ) -> Solution { | 205 | ) -> Solution { |
206 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { | 206 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| { |
207 | let value = subst | 207 | let value = subst |
208 | .value | 208 | .value |
209 | .parameters | 209 | .parameters |
210 | .into_iter() | 210 | .into_iter() |
211 | .map(|p| { | 211 | .map(|p| { |
212 | let ty = match p { | 212 | let ty = match p.ty() { |
213 | chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), | 213 | Some(ty) => from_chalk(db, ty.clone()), |
214 | chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), | 214 | None => unimplemented!(), |
215 | }; | 215 | }; |
216 | ty | 216 | ty |
217 | }) | 217 | }) |
@@ -291,7 +291,7 @@ impl FnTrait { | |||
291 | } | 291 | } |
292 | } | 292 | } |
293 | 293 | ||
294 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 294 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
295 | pub struct ClosureFnTraitImplData { | 295 | pub struct ClosureFnTraitImplData { |
296 | def: DefWithBodyId, | 296 | def: DefWithBodyId, |
297 | expr: ExprId, | 297 | expr: ExprId, |
@@ -300,7 +300,7 @@ pub struct ClosureFnTraitImplData { | |||
300 | 300 | ||
301 | /// An impl. Usually this comes from an impl block, but some built-in types get | 301 | /// An impl. Usually this comes from an impl block, but some built-in types get |
302 | /// synthetic impls. | 302 | /// synthetic impls. |
303 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 303 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
304 | pub enum Impl { | 304 | pub enum Impl { |
305 | /// A normal impl from an impl block. | 305 | /// A normal impl from an impl block. |
306 | ImplBlock(ImplId), | 306 | ImplBlock(ImplId), |
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index cd587a338..dd41176f0 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs | |||
@@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls( | |||
28 | trait_: TraitId, | 28 | trait_: TraitId, |
29 | mut callback: impl FnMut(Impl), | 29 | mut callback: impl FnMut(Impl), |
30 | ) { | 30 | ) { |
31 | // Note: since impl_datum needs to be infallible, we need to make sure here | ||
32 | // that we have all prerequisites to build the respective impls. | ||
31 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { | 33 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { |
32 | for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() | 34 | for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() |
33 | { | 35 | { |
34 | if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { | 36 | if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { |
35 | if trait_ == actual_trait { | 37 | if trait_ == actual_trait { |
36 | let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; | 38 | let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; |
37 | callback(Impl::ClosureFnTraitImpl(impl_)); | 39 | if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { |
40 | callback(Impl::ClosureFnTraitImpl(impl_)); | ||
41 | } | ||
38 | } | 42 | } |
39 | } | 43 | } |
40 | } | 44 | } |
41 | } | 45 | } |
42 | } | 46 | } |
43 | 47 | ||
44 | pub(super) fn impl_datum( | 48 | pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { |
45 | db: &impl HirDatabase, | ||
46 | krate: CrateId, | ||
47 | impl_: Impl, | ||
48 | ) -> Option<BuiltinImplData> { | ||
49 | match impl_ { | 49 | match impl_ { |
50 | Impl::ImplBlock(_) => unreachable!(), | 50 | Impl::ImplBlock(_) => unreachable!(), |
51 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | 51 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
@@ -65,21 +65,38 @@ pub(super) fn associated_ty_value( | |||
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | fn check_closure_fn_trait_impl_prerequisites( | ||
69 | db: &impl HirDatabase, | ||
70 | krate: CrateId, | ||
71 | data: super::ClosureFnTraitImplData, | ||
72 | ) -> bool { | ||
73 | // the respective Fn/FnOnce/FnMut trait needs to exist | ||
74 | if get_fn_trait(db, krate, data.fn_trait).is_none() { | ||
75 | return false; | ||
76 | } | ||
77 | |||
78 | // FIXME: there are more assumptions that we should probably check here: | ||
79 | // the traits having no type params, FnOnce being a supertrait | ||
80 | |||
81 | // the FnOnce trait needs to exist and have an assoc type named Output | ||
82 | let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) { | ||
83 | Some(t) => t, | ||
84 | None => return false, | ||
85 | }; | ||
86 | db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some() | ||
87 | } | ||
88 | |||
68 | fn closure_fn_trait_impl_datum( | 89 | fn closure_fn_trait_impl_datum( |
69 | db: &impl HirDatabase, | 90 | db: &impl HirDatabase, |
70 | krate: CrateId, | 91 | krate: CrateId, |
71 | data: super::ClosureFnTraitImplData, | 92 | data: super::ClosureFnTraitImplData, |
72 | ) -> Option<BuiltinImplData> { | 93 | ) -> BuiltinImplData { |
73 | // for some closure |X, Y| -> Z: | 94 | // for some closure |X, Y| -> Z: |
74 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | 95 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } |
75 | 96 | ||
76 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | 97 | let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait |
77 | 98 | // the existence of the Fn trait has been checked before | |
78 | // validate FnOnce trait, since we need it in the assoc ty value definition | 99 | .expect("fn trait for closure impl missing"); |
79 | // and don't want to return a valid value only to find out later that FnOnce | ||
80 | // is broken | ||
81 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
82 | let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; | ||
83 | 100 | ||
84 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { | 101 | let num_args: u16 = match &db.body(data.def.into())[data.expr] { |
85 | Expr::Lambda { args, .. } => args.len() as u16, | 102 | Expr::Lambda { args, .. } => args.len() as u16, |
@@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum( | |||
107 | 124 | ||
108 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); | 125 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); |
109 | 126 | ||
110 | Some(BuiltinImplData { | 127 | BuiltinImplData { |
111 | num_vars: num_args as usize + 1, | 128 | num_vars: num_args as usize + 1, |
112 | trait_ref, | 129 | trait_ref, |
113 | where_clauses: Vec::new(), | 130 | where_clauses: Vec::new(), |
114 | assoc_ty_values: vec![output_ty_id], | 131 | assoc_ty_values: vec![output_ty_id], |
115 | }) | 132 | } |
116 | } | 133 | } |
117 | 134 | ||
118 | fn closure_fn_trait_output_assoc_ty_value( | 135 | fn closure_fn_trait_output_assoc_ty_value( |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 5eb032d86..555930c9b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -1,17 +1,11 @@ | |||
1 | //! Conversion code from/to Chalk. | 1 | //! Conversion code from/to Chalk. |
2 | use std::sync::Arc; | 2 | use std::{fmt, sync::Arc}; |
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; |
7 | cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId, | ||
8 | TypeName, UniverseIndex, | ||
9 | }; | ||
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | ||
11 | 7 | ||
12 | use hir_def::{ | 8 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; |
13 | AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId, | ||
14 | }; | ||
15 | use ra_db::{ | 9 | use ra_db::{ |
16 | salsa::{InternId, InternKey}, | 10 | salsa::{InternId, InternKey}, |
17 | CrateId, | 11 | CrateId, |
@@ -23,9 +17,83 @@ use crate::{ | |||
23 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 17 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, |
24 | }; | 18 | }; |
25 | 19 | ||
26 | /// This represents a trait whose name we could not resolve. | 20 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] |
27 | const UNKNOWN_TRAIT: chalk_ir::TraitId = | 21 | pub struct TypeFamily {} |
28 | chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); | 22 | |
23 | impl chalk_ir::family::TypeFamily for TypeFamily { | ||
24 | type InternedType = Box<chalk_ir::TyData<Self>>; | ||
25 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
26 | type InternedParameter = chalk_ir::ParameterData<Self>; | ||
27 | type DefId = InternId; | ||
28 | |||
29 | // FIXME: implement these | ||
30 | fn debug_struct_id( | ||
31 | _type_kind_id: chalk_ir::StructId<Self>, | ||
32 | _fmt: &mut fmt::Formatter<'_>, | ||
33 | ) -> Option<fmt::Result> { | ||
34 | None | ||
35 | } | ||
36 | |||
37 | fn debug_trait_id( | ||
38 | _type_kind_id: chalk_ir::TraitId<Self>, | ||
39 | _fmt: &mut fmt::Formatter<'_>, | ||
40 | ) -> Option<fmt::Result> { | ||
41 | None | ||
42 | } | ||
43 | |||
44 | fn debug_assoc_type_id( | ||
45 | _id: chalk_ir::AssocTypeId<Self>, | ||
46 | _fmt: &mut fmt::Formatter<'_>, | ||
47 | ) -> Option<fmt::Result> { | ||
48 | None | ||
49 | } | ||
50 | |||
51 | fn debug_projection( | ||
52 | _projection: &chalk_ir::ProjectionTy<Self>, | ||
53 | _fmt: &mut fmt::Formatter<'_>, | ||
54 | ) -> Option<fmt::Result> { | ||
55 | None | ||
56 | } | ||
57 | |||
58 | fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
59 | Box::new(ty) | ||
60 | } | ||
61 | |||
62 | fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> { | ||
63 | ty | ||
64 | } | ||
65 | |||
66 | fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> { | ||
67 | lifetime | ||
68 | } | ||
69 | |||
70 | fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> { | ||
71 | lifetime | ||
72 | } | ||
73 | |||
74 | fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> { | ||
75 | parameter | ||
76 | } | ||
77 | |||
78 | fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { | ||
79 | parameter | ||
80 | } | ||
81 | } | ||
82 | |||
83 | impl chalk_ir::family::HasTypeFamily for TypeFamily { | ||
84 | type TypeFamily = Self; | ||
85 | } | ||
86 | |||
87 | pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>; | ||
88 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>; | ||
89 | pub type TraitId = chalk_ir::TraitId<TypeFamily>; | ||
90 | pub type TraitDatum = chalk_rust_ir::TraitDatum<TypeFamily>; | ||
91 | pub type StructId = chalk_ir::StructId<TypeFamily>; | ||
92 | pub type StructDatum = chalk_rust_ir::StructDatum<TypeFamily>; | ||
93 | pub type ImplId = chalk_ir::ImplId<TypeFamily>; | ||
94 | pub type ImplDatum = chalk_rust_ir::ImplDatum<TypeFamily>; | ||
95 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; | ||
96 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>; | ||
29 | 97 | ||
30 | pub(super) trait ToChalk { | 98 | pub(super) trait ToChalk { |
31 | type Chalk; | 99 | type Chalk; |
@@ -41,21 +109,11 @@ where | |||
41 | } | 109 | } |
42 | 110 | ||
43 | impl ToChalk for Ty { | 111 | impl ToChalk for Ty { |
44 | type Chalk = chalk_ir::Ty<ChalkIr>; | 112 | type Chalk = chalk_ir::Ty<TypeFamily>; |
45 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> { | 113 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<TypeFamily> { |
46 | match self { | 114 | match self { |
47 | Ty::Apply(apply_ty) => { | 115 | Ty::Apply(apply_ty) => { |
48 | let name = match apply_ty.ctor { | 116 | let name = apply_ty.ctor.to_chalk(db); |
49 | TypeCtor::AssociatedType(type_alias) => { | ||
50 | let type_id = type_alias.to_chalk(db); | ||
51 | TypeName::AssociatedType(type_id) | ||
52 | } | ||
53 | _ => { | ||
54 | // other TypeCtors get interned and turned into a chalk StructId | ||
55 | let struct_id = apply_ty.ctor.to_chalk(db); | ||
56 | TypeName::TypeKindId(struct_id.into()) | ||
57 | } | ||
58 | }; | ||
59 | let parameters = apply_ty.parameters.to_chalk(db); | 117 | let parameters = apply_ty.parameters.to_chalk(db); |
60 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() | 118 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
61 | } | 119 | } |
@@ -65,17 +123,30 @@ impl ToChalk for Ty { | |||
65 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() | 123 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() |
66 | } | 124 | } |
67 | Ty::Param { idx, .. } => { | 125 | Ty::Param { idx, .. } => { |
68 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() | 126 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } |
127 | .to_ty::<TypeFamily>() | ||
69 | } | 128 | } |
70 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), | 129 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), |
71 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 130 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
72 | Ty::Dyn(predicates) => { | 131 | Ty::Dyn(predicates) => { |
73 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | 132 | let where_clauses = predicates |
74 | chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() | 133 | .iter() |
134 | .filter(|p| !p.is_error()) | ||
135 | .cloned() | ||
136 | .map(|p| p.to_chalk(db)) | ||
137 | .collect(); | ||
138 | let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; | ||
139 | chalk_ir::TyData::Dyn(bounded_ty).intern() | ||
75 | } | 140 | } |
76 | Ty::Opaque(predicates) => { | 141 | Ty::Opaque(predicates) => { |
77 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | 142 | let where_clauses = predicates |
78 | chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() | 143 | .iter() |
144 | .filter(|p| !p.is_error()) | ||
145 | .cloned() | ||
146 | .map(|p| p.to_chalk(db)) | ||
147 | .collect(); | ||
148 | let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; | ||
149 | chalk_ir::TyData::Opaque(bounded_ty).intern() | ||
79 | } | 150 | } |
80 | Ty::Unknown => { | 151 | Ty::Unknown => { |
81 | let parameters = Vec::new(); | 152 | let parameters = Vec::new(); |
@@ -84,30 +155,19 @@ impl ToChalk for Ty { | |||
84 | } | 155 | } |
85 | } | 156 | } |
86 | } | 157 | } |
87 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | 158 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<TypeFamily>) -> Self { |
88 | match chalk.data().clone() { | 159 | match chalk.data().clone() { |
89 | chalk_ir::TyData::Apply(apply_ty) => { | 160 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { |
90 | // FIXME this is kind of hacky due to the fact that | 161 | TypeName::Error => Ty::Unknown, |
91 | // TypeName::Placeholder is a Ty::Param on our side | 162 | _ => { |
92 | match apply_ty.name { | 163 | let ctor = from_chalk(db, apply_ty.name); |
93 | TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { | 164 | let parameters = from_chalk(db, apply_ty.parameters); |
94 | let ctor = from_chalk(db, struct_id); | 165 | Ty::Apply(ApplicationTy { ctor, parameters }) |
95 | let parameters = from_chalk(db, apply_ty.parameters); | ||
96 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
97 | } | ||
98 | TypeName::AssociatedType(type_id) => { | ||
99 | let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); | ||
100 | let parameters = from_chalk(db, apply_ty.parameters); | ||
101 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
102 | } | ||
103 | TypeName::Error => Ty::Unknown, | ||
104 | // FIXME handle TypeKindId::Trait/Type here | ||
105 | TypeName::TypeKindId(_) => unimplemented!(), | ||
106 | TypeName::Placeholder(idx) => { | ||
107 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
108 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | ||
109 | } | ||
110 | } | 166 | } |
167 | }, | ||
168 | chalk_ir::TyData::Placeholder(idx) => { | ||
169 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
170 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | ||
111 | } | 171 | } |
112 | chalk_ir::TyData::Projection(proj) => { | 172 | chalk_ir::TyData::Projection(proj) => { |
113 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 173 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
@@ -118,15 +178,15 @@ impl ToChalk for Ty { | |||
118 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), | 178 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
119 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | 179 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
120 | chalk_ir::TyData::Dyn(where_clauses) => { | 180 | chalk_ir::TyData::Dyn(where_clauses) => { |
121 | assert_eq!(where_clauses.binders.len(), 1); | 181 | assert_eq!(where_clauses.bounds.binders.len(), 1); |
122 | let predicates = | 182 | let predicates = |
123 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 183 | where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
124 | Ty::Dyn(predicates) | 184 | Ty::Dyn(predicates) |
125 | } | 185 | } |
126 | chalk_ir::TyData::Opaque(where_clauses) => { | 186 | chalk_ir::TyData::Opaque(where_clauses) => { |
127 | assert_eq!(where_clauses.binders.len(), 1); | 187 | assert_eq!(where_clauses.bounds.binders.len(), 1); |
128 | let predicates = | 188 | let predicates = |
129 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 189 | where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
130 | Ty::Opaque(predicates) | 190 | Ty::Opaque(predicates) |
131 | } | 191 | } |
132 | } | 192 | } |
@@ -134,18 +194,21 @@ impl ToChalk for Ty { | |||
134 | } | 194 | } |
135 | 195 | ||
136 | impl ToChalk for Substs { | 196 | impl ToChalk for Substs { |
137 | type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>; | 197 | type Chalk = Vec<chalk_ir::Parameter<TypeFamily>>; |
138 | 198 | ||
139 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> { | 199 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<TypeFamily>> { |
140 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() | 200 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() |
141 | } | 201 | } |
142 | 202 | ||
143 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs { | 203 | fn from_chalk( |
204 | db: &impl HirDatabase, | ||
205 | parameters: Vec<chalk_ir::Parameter<TypeFamily>>, | ||
206 | ) -> Substs { | ||
144 | let tys = parameters | 207 | let tys = parameters |
145 | .into_iter() | 208 | .into_iter() |
146 | .map(|p| match p { | 209 | .map(|p| match p.ty() { |
147 | chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), | 210 | Some(ty) => from_chalk(db, ty.clone()), |
148 | chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), | 211 | None => unimplemented!(), |
149 | }) | 212 | }) |
150 | .collect(); | 213 | .collect(); |
151 | Substs(tys) | 214 | Substs(tys) |
@@ -153,88 +216,102 @@ impl ToChalk for Substs { | |||
153 | } | 216 | } |
154 | 217 | ||
155 | impl ToChalk for TraitRef { | 218 | impl ToChalk for TraitRef { |
156 | type Chalk = chalk_ir::TraitRef<ChalkIr>; | 219 | type Chalk = chalk_ir::TraitRef<TypeFamily>; |
157 | 220 | ||
158 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> { | 221 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<TypeFamily> { |
159 | let trait_id = self.trait_.to_chalk(db); | 222 | let trait_id = self.trait_.to_chalk(db); |
160 | let parameters = self.substs.to_chalk(db); | 223 | let parameters = self.substs.to_chalk(db); |
161 | chalk_ir::TraitRef { trait_id, parameters } | 224 | chalk_ir::TraitRef { trait_id, parameters } |
162 | } | 225 | } |
163 | 226 | ||
164 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self { | 227 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<TypeFamily>) -> Self { |
165 | let trait_ = from_chalk(db, trait_ref.trait_id); | 228 | let trait_ = from_chalk(db, trait_ref.trait_id); |
166 | let substs = from_chalk(db, trait_ref.parameters); | 229 | let substs = from_chalk(db, trait_ref.parameters); |
167 | TraitRef { trait_, substs } | 230 | TraitRef { trait_, substs } |
168 | } | 231 | } |
169 | } | 232 | } |
170 | 233 | ||
171 | impl ToChalk for TraitId { | 234 | impl ToChalk for hir_def::TraitId { |
172 | type Chalk = chalk_ir::TraitId; | 235 | type Chalk = TraitId; |
173 | 236 | ||
174 | fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { | 237 | fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { |
175 | chalk_ir::TraitId(id_to_chalk(self)) | 238 | chalk_ir::TraitId(self.as_intern_id()) |
176 | } | 239 | } |
177 | 240 | ||
178 | fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId { | 241 | fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { |
179 | id_from_chalk(trait_id.0) | 242 | InternKey::from_intern_id(trait_id.0) |
180 | } | 243 | } |
181 | } | 244 | } |
182 | 245 | ||
183 | impl ToChalk for TypeCtor { | 246 | impl ToChalk for TypeCtor { |
184 | type Chalk = chalk_ir::StructId; | 247 | type Chalk = TypeName<TypeFamily>; |
185 | 248 | ||
186 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { | 249 | fn to_chalk(self, db: &impl HirDatabase) -> TypeName<TypeFamily> { |
187 | db.intern_type_ctor(self).into() | 250 | match self { |
251 | TypeCtor::AssociatedType(type_alias) => { | ||
252 | let type_id = type_alias.to_chalk(db); | ||
253 | TypeName::AssociatedType(type_id) | ||
254 | } | ||
255 | _ => { | ||
256 | // other TypeCtors get interned and turned into a chalk StructId | ||
257 | let struct_id = db.intern_type_ctor(self).into(); | ||
258 | TypeName::Struct(struct_id) | ||
259 | } | ||
260 | } | ||
188 | } | 261 | } |
189 | 262 | ||
190 | fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { | 263 | fn from_chalk(db: &impl HirDatabase, type_name: TypeName<TypeFamily>) -> TypeCtor { |
191 | db.lookup_intern_type_ctor(struct_id.into()) | 264 | match type_name { |
265 | TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | ||
266 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | ||
267 | TypeName::Error => { | ||
268 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | ||
269 | unreachable!() | ||
270 | } | ||
271 | } | ||
192 | } | 272 | } |
193 | } | 273 | } |
194 | 274 | ||
195 | impl ToChalk for Impl { | 275 | impl ToChalk for Impl { |
196 | type Chalk = chalk_ir::ImplId; | 276 | type Chalk = ImplId; |
197 | 277 | ||
198 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { | 278 | fn to_chalk(self, db: &impl HirDatabase) -> ImplId { |
199 | db.intern_chalk_impl(self).into() | 279 | db.intern_chalk_impl(self).into() |
200 | } | 280 | } |
201 | 281 | ||
202 | fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { | 282 | fn from_chalk(db: &impl HirDatabase, impl_id: ImplId) -> Impl { |
203 | db.lookup_intern_chalk_impl(impl_id.into()) | 283 | db.lookup_intern_chalk_impl(impl_id.into()) |
204 | } | 284 | } |
205 | } | 285 | } |
206 | 286 | ||
207 | impl ToChalk for TypeAliasId { | 287 | impl ToChalk for TypeAliasId { |
208 | type Chalk = chalk_ir::TypeId; | 288 | type Chalk = AssocTypeId; |
209 | 289 | ||
210 | fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { | 290 | fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { |
211 | chalk_ir::TypeId(id_to_chalk(self)) | 291 | chalk_ir::AssocTypeId(self.as_intern_id()) |
212 | } | 292 | } |
213 | 293 | ||
214 | fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId { | 294 | fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { |
215 | id_from_chalk(type_alias_id.0) | 295 | InternKey::from_intern_id(type_alias_id.0) |
216 | } | 296 | } |
217 | } | 297 | } |
218 | 298 | ||
219 | impl ToChalk for AssocTyValue { | 299 | impl ToChalk for AssocTyValue { |
220 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | 300 | type Chalk = AssociatedTyValueId; |
221 | 301 | ||
222 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | 302 | fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValueId { |
223 | db.intern_assoc_ty_value(self).into() | 303 | db.intern_assoc_ty_value(self).into() |
224 | } | 304 | } |
225 | 305 | ||
226 | fn from_chalk( | 306 | fn from_chalk(db: &impl HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { |
227 | db: &impl HirDatabase, | ||
228 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
229 | ) -> AssocTyValue { | ||
230 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | 307 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) |
231 | } | 308 | } |
232 | } | 309 | } |
233 | 310 | ||
234 | impl ToChalk for GenericPredicate { | 311 | impl ToChalk for GenericPredicate { |
235 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | 312 | type Chalk = chalk_ir::QuantifiedWhereClause<TypeFamily>; |
236 | 313 | ||
237 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> { | 314 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<TypeFamily> { |
238 | match self { | 315 | match self { |
239 | GenericPredicate::Implemented(trait_ref) => { | 316 | GenericPredicate::Implemented(trait_ref) => { |
240 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | 317 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) |
@@ -246,26 +323,16 @@ impl ToChalk for GenericPredicate { | |||
246 | }), | 323 | }), |
247 | 0, | 324 | 0, |
248 | ), | 325 | ), |
249 | GenericPredicate::Error => { | 326 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), |
250 | let impossible_trait_ref = chalk_ir::TraitRef { | ||
251 | trait_id: UNKNOWN_TRAIT, | ||
252 | parameters: vec![Ty::Unknown.to_chalk(db).cast()], | ||
253 | }; | ||
254 | make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) | ||
255 | } | ||
256 | } | 327 | } |
257 | } | 328 | } |
258 | 329 | ||
259 | fn from_chalk( | 330 | fn from_chalk( |
260 | db: &impl HirDatabase, | 331 | db: &impl HirDatabase, |
261 | where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>, | 332 | where_clause: chalk_ir::QuantifiedWhereClause<TypeFamily>, |
262 | ) -> GenericPredicate { | 333 | ) -> GenericPredicate { |
263 | match where_clause.value { | 334 | match where_clause.value { |
264 | chalk_ir::WhereClause::Implemented(tr) => { | 335 | chalk_ir::WhereClause::Implemented(tr) => { |
265 | if tr.trait_id == UNKNOWN_TRAIT { | ||
266 | // FIXME we need an Error enum on the Chalk side to avoid this | ||
267 | return GenericPredicate::Error; | ||
268 | } | ||
269 | GenericPredicate::Implemented(from_chalk(db, tr)) | 336 | GenericPredicate::Implemented(from_chalk(db, tr)) |
270 | } | 337 | } |
271 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { | 338 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { |
@@ -278,9 +345,9 @@ impl ToChalk for GenericPredicate { | |||
278 | } | 345 | } |
279 | 346 | ||
280 | impl ToChalk for ProjectionTy { | 347 | impl ToChalk for ProjectionTy { |
281 | type Chalk = chalk_ir::ProjectionTy<ChalkIr>; | 348 | type Chalk = chalk_ir::ProjectionTy<TypeFamily>; |
282 | 349 | ||
283 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> { | 350 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<TypeFamily> { |
284 | chalk_ir::ProjectionTy { | 351 | chalk_ir::ProjectionTy { |
285 | associated_ty_id: self.associated_ty.to_chalk(db), | 352 | associated_ty_id: self.associated_ty.to_chalk(db), |
286 | parameters: self.parameters.to_chalk(db), | 353 | parameters: self.parameters.to_chalk(db), |
@@ -289,7 +356,7 @@ impl ToChalk for ProjectionTy { | |||
289 | 356 | ||
290 | fn from_chalk( | 357 | fn from_chalk( |
291 | db: &impl HirDatabase, | 358 | db: &impl HirDatabase, |
292 | projection_ty: chalk_ir::ProjectionTy<ChalkIr>, | 359 | projection_ty: chalk_ir::ProjectionTy<TypeFamily>, |
293 | ) -> ProjectionTy { | 360 | ) -> ProjectionTy { |
294 | ProjectionTy { | 361 | ProjectionTy { |
295 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | 362 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), |
@@ -299,31 +366,31 @@ impl ToChalk for ProjectionTy { | |||
299 | } | 366 | } |
300 | 367 | ||
301 | impl ToChalk for super::ProjectionPredicate { | 368 | impl ToChalk for super::ProjectionPredicate { |
302 | type Chalk = chalk_ir::Normalize<ChalkIr>; | 369 | type Chalk = chalk_ir::Normalize<TypeFamily>; |
303 | 370 | ||
304 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> { | 371 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<TypeFamily> { |
305 | chalk_ir::Normalize { | 372 | chalk_ir::Normalize { |
306 | projection: self.projection_ty.to_chalk(db), | 373 | projection: self.projection_ty.to_chalk(db), |
307 | ty: self.ty.to_chalk(db), | 374 | ty: self.ty.to_chalk(db), |
308 | } | 375 | } |
309 | } | 376 | } |
310 | 377 | ||
311 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self { | 378 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<TypeFamily>) -> Self { |
312 | unimplemented!() | 379 | unimplemented!() |
313 | } | 380 | } |
314 | } | 381 | } |
315 | 382 | ||
316 | impl ToChalk for Obligation { | 383 | impl ToChalk for Obligation { |
317 | type Chalk = chalk_ir::DomainGoal<ChalkIr>; | 384 | type Chalk = chalk_ir::DomainGoal<TypeFamily>; |
318 | 385 | ||
319 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> { | 386 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<TypeFamily> { |
320 | match self { | 387 | match self { |
321 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), | 388 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), |
322 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), | 389 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), |
323 | } | 390 | } |
324 | } | 391 | } |
325 | 392 | ||
326 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self { | 393 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<TypeFamily>) -> Self { |
327 | unimplemented!() | 394 | unimplemented!() |
328 | } | 395 | } |
329 | } | 396 | } |
@@ -347,16 +414,17 @@ where | |||
347 | } | 414 | } |
348 | 415 | ||
349 | impl ToChalk for Arc<super::TraitEnvironment> { | 416 | impl ToChalk for Arc<super::TraitEnvironment> { |
350 | type Chalk = chalk_ir::Environment<ChalkIr>; | 417 | type Chalk = chalk_ir::Environment<TypeFamily>; |
351 | 418 | ||
352 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<ChalkIr> { | 419 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<TypeFamily> { |
353 | let mut clauses = Vec::new(); | 420 | let mut clauses = Vec::new(); |
354 | for pred in &self.predicates { | 421 | for pred in &self.predicates { |
355 | if pred.is_error() { | 422 | if pred.is_error() { |
356 | // for env, we just ignore errors | 423 | // for env, we just ignore errors |
357 | continue; | 424 | continue; |
358 | } | 425 | } |
359 | let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast(); | 426 | let program_clause: chalk_ir::ProgramClause<TypeFamily> = |
427 | pred.clone().to_chalk(db).cast(); | ||
360 | clauses.push(program_clause.into_from_env_clause()); | 428 | clauses.push(program_clause.into_from_env_clause()); |
361 | } | 429 | } |
362 | chalk_ir::Environment::new().add_clauses(clauses) | 430 | chalk_ir::Environment::new().add_clauses(clauses) |
@@ -364,7 +432,7 @@ impl ToChalk for Arc<super::TraitEnvironment> { | |||
364 | 432 | ||
365 | fn from_chalk( | 433 | fn from_chalk( |
366 | _db: &impl HirDatabase, | 434 | _db: &impl HirDatabase, |
367 | _env: chalk_ir::Environment<ChalkIr>, | 435 | _env: chalk_ir::Environment<TypeFamily>, |
368 | ) -> Arc<super::TraitEnvironment> { | 436 | ) -> Arc<super::TraitEnvironment> { |
369 | unimplemented!() | 437 | unimplemented!() |
370 | } | 438 | } |
@@ -372,7 +440,7 @@ impl ToChalk for Arc<super::TraitEnvironment> { | |||
372 | 440 | ||
373 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> | 441 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> |
374 | where | 442 | where |
375 | T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>, | 443 | T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = TypeFamily>, |
376 | { | 444 | { |
377 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 445 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
378 | 446 | ||
@@ -395,9 +463,9 @@ where | |||
395 | } | 463 | } |
396 | 464 | ||
397 | impl ToChalk for builtin::BuiltinImplData { | 465 | impl ToChalk for builtin::BuiltinImplData { |
398 | type Chalk = chalk_rust_ir::ImplDatum<ChalkIr>; | 466 | type Chalk = ImplDatum; |
399 | 467 | ||
400 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum<ChalkIr> { | 468 | fn to_chalk(self, db: &impl HirDatabase) -> ImplDatum { |
401 | let impl_type = chalk_rust_ir::ImplType::External; | 469 | let impl_type = chalk_rust_ir::ImplType::External; |
402 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | 470 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); |
403 | 471 | ||
@@ -413,15 +481,15 @@ impl ToChalk for builtin::BuiltinImplData { | |||
413 | } | 481 | } |
414 | } | 482 | } |
415 | 483 | ||
416 | fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum<ChalkIr>) -> Self { | 484 | fn from_chalk(_db: &impl HirDatabase, _data: ImplDatum) -> Self { |
417 | unimplemented!() | 485 | unimplemented!() |
418 | } | 486 | } |
419 | } | 487 | } |
420 | 488 | ||
421 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | 489 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { |
422 | type Chalk = chalk_rust_ir::AssociatedTyValue<ChalkIr>; | 490 | type Chalk = AssociatedTyValue; |
423 | 491 | ||
424 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue<ChalkIr> { | 492 | fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValue { |
425 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; | 493 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; |
426 | 494 | ||
427 | chalk_rust_ir::AssociatedTyValue { | 495 | chalk_rust_ir::AssociatedTyValue { |
@@ -433,7 +501,7 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData { | |||
433 | 501 | ||
434 | fn from_chalk( | 502 | fn from_chalk( |
435 | _db: &impl HirDatabase, | 503 | _db: &impl HirDatabase, |
436 | _data: chalk_rust_ir::AssociatedTyValue<ChalkIr>, | 504 | _data: AssociatedTyValue, |
437 | ) -> builtin::BuiltinImplAssocTyValueData { | 505 | ) -> builtin::BuiltinImplAssocTyValueData { |
438 | unimplemented!() | 506 | unimplemented!() |
439 | } | 507 | } |
@@ -450,46 +518,46 @@ fn convert_where_clauses( | |||
450 | db: &impl HirDatabase, | 518 | db: &impl HirDatabase, |
451 | def: GenericDefId, | 519 | def: GenericDefId, |
452 | substs: &Substs, | 520 | substs: &Substs, |
453 | ) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { | 521 | ) -> Vec<chalk_ir::QuantifiedWhereClause<TypeFamily>> { |
454 | let generic_predicates = db.generic_predicates(def); | 522 | let generic_predicates = db.generic_predicates(def); |
455 | let mut result = Vec::with_capacity(generic_predicates.len()); | 523 | let mut result = Vec::with_capacity(generic_predicates.len()); |
456 | for pred in generic_predicates.iter() { | 524 | for pred in generic_predicates.iter() { |
457 | if pred.is_error() { | 525 | if pred.is_error() { |
458 | // HACK: Return just the single predicate (which is always false | 526 | // skip errored predicates completely |
459 | // anyway), otherwise Chalk can easily get into slow situations | 527 | continue; |
460 | return vec![pred.clone().subst(substs).to_chalk(db)]; | ||
461 | } | 528 | } |
462 | result.push(pred.clone().subst(substs).to_chalk(db)); | 529 | result.push(pred.clone().subst(substs).to_chalk(db)); |
463 | } | 530 | } |
464 | result | 531 | result |
465 | } | 532 | } |
466 | 533 | ||
467 | impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> | 534 | impl<'a, DB> chalk_solve::RustIrDatabase<TypeFamily> for ChalkContext<'a, DB> |
468 | where | 535 | where |
469 | DB: HirDatabase, | 536 | DB: HirDatabase, |
470 | { | 537 | { |
471 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { | 538 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { |
472 | self.db.associated_ty_data(id) | 539 | self.db.associated_ty_data(id) |
473 | } | 540 | } |
474 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { | 541 | fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> { |
475 | self.db.trait_datum(self.krate, trait_id) | 542 | self.db.trait_datum(self.krate, trait_id) |
476 | } | 543 | } |
477 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { | 544 | fn struct_datum(&self, struct_id: StructId) -> Arc<StructDatum> { |
478 | self.db.struct_datum(self.krate, struct_id) | 545 | self.db.struct_datum(self.krate, struct_id) |
479 | } | 546 | } |
480 | fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc<ImplDatum<ChalkIr>> { | 547 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { |
481 | self.db.impl_datum(self.krate, impl_id) | 548 | self.db.impl_datum(self.krate, impl_id) |
482 | } | 549 | } |
483 | fn impls_for_trait( | 550 | fn impls_for_trait( |
484 | &self, | 551 | &self, |
485 | trait_id: chalk_ir::TraitId, | 552 | trait_id: TraitId, |
486 | parameters: &[Parameter<ChalkIr>], | 553 | parameters: &[Parameter<TypeFamily>], |
487 | ) -> Vec<chalk_ir::ImplId> { | 554 | ) -> Vec<ImplId> { |
488 | debug!("impls_for_trait {:?}", trait_id); | 555 | debug!("impls_for_trait {:?}", trait_id); |
489 | if trait_id == UNKNOWN_TRAIT { | 556 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
490 | return Vec::new(); | 557 | |
491 | } | 558 | // Note: Since we're using impls_for_trait, only impls where the trait |
492 | let trait_: TraitId = from_chalk(self.db, trait_id); | 559 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
560 | // and will panic if the trait can't be resolved. | ||
493 | let mut result: Vec<_> = self | 561 | let mut result: Vec<_> = self |
494 | .db | 562 | .db |
495 | .impls_for_trait(self.krate, trait_.into()) | 563 | .impls_for_trait(self.krate, trait_.into()) |
@@ -508,39 +576,32 @@ where | |||
508 | debug!("impls_for_trait returned {} impls", result.len()); | 576 | debug!("impls_for_trait returned {} impls", result.len()); |
509 | result | 577 | result |
510 | } | 578 | } |
511 | fn impl_provided_for( | 579 | fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool { |
512 | &self, | ||
513 | auto_trait_id: chalk_ir::TraitId, | ||
514 | struct_id: chalk_ir::StructId, | ||
515 | ) -> bool { | ||
516 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); | 580 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); |
517 | false // FIXME | 581 | false // FIXME |
518 | } | 582 | } |
519 | fn type_name(&self, _id: TypeKindId) -> Identifier { | 583 | fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> { |
520 | unimplemented!() | ||
521 | } | ||
522 | fn associated_ty_value( | ||
523 | &self, | ||
524 | id: chalk_rust_ir::AssociatedTyValueId, | ||
525 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
526 | self.db.associated_ty_value(self.krate.into(), id) | 584 | self.db.associated_ty_value(self.krate.into(), id) |
527 | } | 585 | } |
528 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | 586 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<TypeFamily>> { |
529 | vec![] | 587 | vec![] |
530 | } | 588 | } |
531 | fn local_impls_to_coherence_check( | 589 | fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec<ImplId> { |
532 | &self, | ||
533 | _trait_id: chalk_ir::TraitId, | ||
534 | ) -> Vec<chalk_ir::ImplId> { | ||
535 | // We don't do coherence checking (yet) | 590 | // We don't do coherence checking (yet) |
536 | unimplemented!() | 591 | unimplemented!() |
537 | } | 592 | } |
593 | fn as_struct_id(&self, id: &TypeName<TypeFamily>) -> Option<StructId> { | ||
594 | match id { | ||
595 | TypeName::Struct(struct_id) => Some(*struct_id), | ||
596 | _ => None, | ||
597 | } | ||
598 | } | ||
538 | } | 599 | } |
539 | 600 | ||
540 | pub(crate) fn associated_ty_data_query( | 601 | pub(crate) fn associated_ty_data_query( |
541 | db: &impl HirDatabase, | 602 | db: &impl HirDatabase, |
542 | id: TypeId, | 603 | id: AssocTypeId, |
543 | ) -> Arc<AssociatedTyDatum<ChalkIr>> { | 604 | ) -> Arc<AssociatedTyDatum> { |
544 | debug!("associated_ty_data {:?}", id); | 605 | debug!("associated_ty_data {:?}", id); |
545 | let type_alias: TypeAliasId = from_chalk(db, id); | 606 | let type_alias: TypeAliasId = from_chalk(db, id); |
546 | let trait_ = match type_alias.lookup(db).container { | 607 | let trait_ = match type_alias.lookup(db).container { |
@@ -565,28 +626,10 @@ pub(crate) fn associated_ty_data_query( | |||
565 | pub(crate) fn trait_datum_query( | 626 | pub(crate) fn trait_datum_query( |
566 | db: &impl HirDatabase, | 627 | db: &impl HirDatabase, |
567 | krate: CrateId, | 628 | krate: CrateId, |
568 | trait_id: chalk_ir::TraitId, | 629 | trait_id: TraitId, |
569 | ) -> Arc<TraitDatum<ChalkIr>> { | 630 | ) -> Arc<TraitDatum> { |
570 | debug!("trait_datum {:?}", trait_id); | 631 | debug!("trait_datum {:?}", trait_id); |
571 | if trait_id == UNKNOWN_TRAIT { | 632 | let trait_: hir_def::TraitId = from_chalk(db, trait_id); |
572 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; | ||
573 | |||
574 | let flags = chalk_rust_ir::TraitFlags { | ||
575 | auto: false, | ||
576 | marker: false, | ||
577 | upstream: true, | ||
578 | fundamental: false, | ||
579 | non_enumerable: true, | ||
580 | coinductive: false, | ||
581 | }; | ||
582 | return Arc::new(TraitDatum { | ||
583 | id: trait_id, | ||
584 | binders: make_binders(trait_datum_bound, 1), | ||
585 | flags, | ||
586 | associated_ty_ids: vec![], | ||
587 | }); | ||
588 | } | ||
589 | let trait_: TraitId = from_chalk(db, trait_id); | ||
590 | let trait_data = db.trait_data(trait_); | 633 | let trait_data = db.trait_data(trait_); |
591 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); | 634 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); |
592 | let generic_params = generics(db, trait_.into()); | 635 | let generic_params = generics(db, trait_.into()); |
@@ -616,10 +659,10 @@ pub(crate) fn trait_datum_query( | |||
616 | pub(crate) fn struct_datum_query( | 659 | pub(crate) fn struct_datum_query( |
617 | db: &impl HirDatabase, | 660 | db: &impl HirDatabase, |
618 | krate: CrateId, | 661 | krate: CrateId, |
619 | struct_id: chalk_ir::StructId, | 662 | struct_id: StructId, |
620 | ) -> Arc<StructDatum<ChalkIr>> { | 663 | ) -> Arc<StructDatum> { |
621 | debug!("struct_datum {:?}", struct_id); | 664 | debug!("struct_datum {:?}", struct_id); |
622 | let type_ctor: TypeCtor = from_chalk(db, struct_id); | 665 | let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id)); |
623 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 666 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
624 | let num_params = type_ctor.num_ty_params(db); | 667 | let num_params = type_ctor.num_ty_params(db); |
625 | let upstream = type_ctor.krate(db) != Some(krate); | 668 | let upstream = type_ctor.krate(db) != Some(krate); |
@@ -648,25 +691,27 @@ pub(crate) fn struct_datum_query( | |||
648 | pub(crate) fn impl_datum_query( | 691 | pub(crate) fn impl_datum_query( |
649 | db: &impl HirDatabase, | 692 | db: &impl HirDatabase, |
650 | krate: CrateId, | 693 | krate: CrateId, |
651 | impl_id: chalk_ir::ImplId, | 694 | impl_id: ImplId, |
652 | ) -> Arc<ImplDatum<ChalkIr>> { | 695 | ) -> Arc<ImplDatum> { |
653 | let _p = ra_prof::profile("impl_datum"); | 696 | let _p = ra_prof::profile("impl_datum"); |
654 | debug!("impl_datum {:?}", impl_id); | 697 | debug!("impl_datum {:?}", impl_id); |
655 | let impl_: Impl = from_chalk(db, impl_id); | 698 | let impl_: Impl = from_chalk(db, impl_id); |
656 | match impl_ { | 699 | match impl_ { |
657 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 700 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
658 | _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), | 701 | _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)), |
659 | } | 702 | } |
660 | .unwrap_or_else(invalid_impl_datum) | ||
661 | } | 703 | } |
662 | 704 | ||
663 | fn impl_block_datum( | 705 | fn impl_block_datum( |
664 | db: &impl HirDatabase, | 706 | db: &impl HirDatabase, |
665 | krate: CrateId, | 707 | krate: CrateId, |
666 | chalk_id: chalk_ir::ImplId, | 708 | chalk_id: ImplId, |
667 | impl_id: ImplId, | 709 | impl_id: hir_def::ImplId, |
668 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | 710 | ) -> Arc<ImplDatum> { |
669 | let trait_ref = db.impl_trait(impl_id)?; | 711 | let trait_ref = db |
712 | .impl_trait(impl_id) | ||
713 | // ImplIds for impls where the trait ref can't be resolved should never reach Chalk | ||
714 | .expect("invalid impl passed to Chalk"); | ||
670 | let impl_data = db.impl_data(impl_id); | 715 | let impl_data = db.impl_data(impl_id); |
671 | 716 | ||
672 | let generic_params = generics(db, impl_id.into()); | 717 | let generic_params = generics(db, impl_id.into()); |
@@ -718,29 +763,14 @@ fn impl_block_datum( | |||
718 | polarity, | 763 | polarity, |
719 | associated_ty_value_ids, | 764 | associated_ty_value_ids, |
720 | }; | 765 | }; |
721 | Some(Arc::new(impl_datum)) | ||
722 | } | ||
723 | |||
724 | fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { | ||
725 | let trait_ref = chalk_ir::TraitRef { | ||
726 | trait_id: UNKNOWN_TRAIT, | ||
727 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], | ||
728 | }; | ||
729 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
730 | let impl_datum = ImplDatum { | ||
731 | binders: make_binders(impl_datum_bound, 1), | ||
732 | impl_type: chalk_rust_ir::ImplType::External, | ||
733 | polarity: chalk_rust_ir::Polarity::Positive, | ||
734 | associated_ty_value_ids: Vec::new(), | ||
735 | }; | ||
736 | Arc::new(impl_datum) | 766 | Arc::new(impl_datum) |
737 | } | 767 | } |
738 | 768 | ||
739 | pub(crate) fn associated_ty_value_query( | 769 | pub(crate) fn associated_ty_value_query( |
740 | db: &impl HirDatabase, | 770 | db: &impl HirDatabase, |
741 | krate: CrateId, | 771 | krate: CrateId, |
742 | id: chalk_rust_ir::AssociatedTyValueId, | 772 | id: AssociatedTyValueId, |
743 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { | 773 | ) -> Arc<AssociatedTyValue> { |
744 | let data: AssocTyValue = from_chalk(db, id); | 774 | let data: AssocTyValue = from_chalk(db, id); |
745 | match data { | 775 | match data { |
746 | AssocTyValue::TypeAlias(type_alias) => { | 776 | AssocTyValue::TypeAlias(type_alias) => { |
@@ -754,7 +784,7 @@ fn type_alias_associated_ty_value( | |||
754 | db: &impl HirDatabase, | 784 | db: &impl HirDatabase, |
755 | _krate: CrateId, | 785 | _krate: CrateId, |
756 | type_alias: TypeAliasId, | 786 | type_alias: TypeAliasId, |
757 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | 787 | ) -> Arc<AssociatedTyValue> { |
758 | let type_alias_data = db.type_alias_data(type_alias); | 788 | let type_alias_data = db.type_alias_data(type_alias); |
759 | let impl_id = match type_alias.lookup(db).container { | 789 | let impl_id = match type_alias.lookup(db).container { |
760 | AssocContainerId::ImplId(it) => it, | 790 | AssocContainerId::ImplId(it) => it, |
@@ -786,27 +816,27 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId { | |||
786 | chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } | 816 | chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } |
787 | } | 817 | } |
788 | 818 | ||
789 | impl From<chalk_ir::StructId> for crate::TypeCtorId { | 819 | impl From<StructId> for crate::TypeCtorId { |
790 | fn from(struct_id: chalk_ir::StructId) -> Self { | 820 | fn from(struct_id: StructId) -> Self { |
791 | id_from_chalk(struct_id.0) | 821 | InternKey::from_intern_id(struct_id.0) |
792 | } | 822 | } |
793 | } | 823 | } |
794 | 824 | ||
795 | impl From<crate::TypeCtorId> for chalk_ir::StructId { | 825 | impl From<crate::TypeCtorId> for StructId { |
796 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { | 826 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { |
797 | chalk_ir::StructId(id_to_chalk(type_ctor_id)) | 827 | chalk_ir::StructId(type_ctor_id.as_intern_id()) |
798 | } | 828 | } |
799 | } | 829 | } |
800 | 830 | ||
801 | impl From<chalk_ir::ImplId> for crate::traits::GlobalImplId { | 831 | impl From<ImplId> for crate::traits::GlobalImplId { |
802 | fn from(impl_id: chalk_ir::ImplId) -> Self { | 832 | fn from(impl_id: ImplId) -> Self { |
803 | id_from_chalk(impl_id.0) | 833 | InternKey::from_intern_id(impl_id.0) |
804 | } | 834 | } |
805 | } | 835 | } |
806 | 836 | ||
807 | impl From<crate::traits::GlobalImplId> for chalk_ir::ImplId { | 837 | impl From<crate::traits::GlobalImplId> for ImplId { |
808 | fn from(impl_id: crate::traits::GlobalImplId) -> Self { | 838 | fn from(impl_id: crate::traits::GlobalImplId) -> Self { |
809 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 839 | chalk_ir::ImplId(impl_id.as_intern_id()) |
810 | } | 840 | } |
811 | } | 841 | } |
812 | 842 | ||
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index e826c10ef..030e9033c 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -14,7 +14,7 @@ serde_json = "1.0.34" | |||
14 | serde = { version = "1.0.83", features = ["derive"] } | 14 | serde = { version = "1.0.83", features = ["derive"] } |
15 | crossbeam-channel = "0.4" | 15 | crossbeam-channel = "0.4" |
16 | log = "0.4.3" | 16 | log = "0.4.3" |
17 | lsp-types = { version = "0.65.0", features = ["proposed"] } | 17 | lsp-types = { version = "0.67.0", features = ["proposed"] } |
18 | rustc-hash = "1.0" | 18 | rustc-hash = "1.0" |
19 | parking_lot = "0.10.0" | 19 | parking_lot = "0.10.0" |
20 | jod-thread = "0.1.0" | 20 | jod-thread = "0.1.0" |
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index eeca67ee1..ceb4c4259 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -46,6 +46,7 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
46 | more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), | 46 | more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), |
47 | }), | 47 | }), |
48 | selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), | 48 | selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), |
49 | semantic_highlighting: None, | ||
49 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | 50 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), |
50 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions { | 51 | rename_provider: Some(RenameProviderCapability::Options(RenameOptions { |
51 | prepare_provider: Some(true), | 52 | prepare_provider: Some(true), |
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index a8f625176..baaef3023 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -221,6 +221,10 @@ impl ast::FnDef { | |||
221 | .and_then(|it| it.into_token()) | 221 | .and_then(|it| it.into_token()) |
222 | .filter(|it| it.kind() == T![;]) | 222 | .filter(|it| it.kind() == T![;]) |
223 | } | 223 | } |
224 | |||
225 | pub fn is_async(&self) -> bool { | ||
226 | self.syntax().children_with_tokens().any(|it| it.kind() == T![async]) | ||
227 | } | ||
224 | } | 228 | } |
225 | 229 | ||
226 | impl ast::LetStmt { | 230 | impl ast::LetStmt { |
diff --git a/docs/user/assists.md b/docs/user/assists.md index 334ba450f..ecf206f71 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -98,26 +98,26 @@ Adds scaffold for overriding default impl members. | |||
98 | 98 | ||
99 | ```rust | 99 | ```rust |
100 | // BEFORE | 100 | // BEFORE |
101 | trait T { | 101 | trait Trait { |
102 | Type X; | 102 | Type X; |
103 | fn foo(&self); | 103 | fn foo(&self); |
104 | fn bar(&self) {} | 104 | fn bar(&self) {} |
105 | } | 105 | } |
106 | 106 | ||
107 | impl T for () { | 107 | impl Trait for () { |
108 | Type X = (); | 108 | Type X = (); |
109 | fn foo(&self) {}┃ | 109 | fn foo(&self) {}┃ |
110 | 110 | ||
111 | } | 111 | } |
112 | 112 | ||
113 | // AFTER | 113 | // AFTER |
114 | trait T { | 114 | trait Trait { |
115 | Type X; | 115 | Type X; |
116 | fn foo(&self); | 116 | fn foo(&self); |
117 | fn bar(&self) {} | 117 | fn bar(&self) {} |
118 | } | 118 | } |
119 | 119 | ||
120 | impl T for () { | 120 | impl Trait for () { |
121 | Type X = (); | 121 | Type X = (); |
122 | fn foo(&self) {} | 122 | fn foo(&self) {} |
123 | fn bar(&self) {} | 123 | fn bar(&self) {} |
@@ -131,25 +131,25 @@ Adds scaffold for required impl members. | |||
131 | 131 | ||
132 | ```rust | 132 | ```rust |
133 | // BEFORE | 133 | // BEFORE |
134 | trait T { | 134 | trait Trait<T> { |
135 | Type X; | 135 | Type X; |
136 | fn foo(&self); | 136 | fn foo(&self) -> T; |
137 | fn bar(&self) {} | 137 | fn bar(&self) {} |
138 | } | 138 | } |
139 | 139 | ||
140 | impl T for () {┃ | 140 | impl Trait<u32> for () {┃ |
141 | 141 | ||
142 | } | 142 | } |
143 | 143 | ||
144 | // AFTER | 144 | // AFTER |
145 | trait T { | 145 | trait Trait<T> { |
146 | Type X; | 146 | Type X; |
147 | fn foo(&self); | 147 | fn foo(&self) -> T; |
148 | fn bar(&self) {} | 148 | fn bar(&self) {} |
149 | } | 149 | } |
150 | 150 | ||
151 | impl T for () { | 151 | impl Trait<u32> for () { |
152 | fn foo(&self) { unimplemented!() } | 152 | fn foo(&self) -> u32 { unimplemented!() } |
153 | 153 | ||
154 | } | 154 | } |
155 | ``` | 155 | ``` |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4201c6a6a..9cefad925 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -226,7 +226,7 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | |||
226 | if !str::from_utf8(&output.stdout)?.contains("ra-lsp") { | 226 | if !str::from_utf8(&output.stdout)?.contains("ra-lsp") { |
227 | anyhow::bail!( | 227 | anyhow::bail!( |
228 | "Could not install the Visual Studio Code extension. \ | 228 | "Could not install the Visual Studio Code extension. \ |
229 | Please make sure you have at least NodeJS 10.x installed and try again." | 229 | Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again." |
230 | ); | 230 | ); |
231 | } | 231 | } |
232 | 232 | ||