diff options
91 files changed, 1385 insertions, 779 deletions
diff --git a/Cargo.lock b/Cargo.lock index 76a26ea4e..557d5f5f3 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -4,9 +4,9 @@ version = 3 | |||
4 | 4 | ||
5 | [[package]] | 5 | [[package]] |
6 | name = "addr2line" | 6 | name = "addr2line" |
7 | version = "0.14.1" | 7 | version = "0.15.1" |
8 | source = "registry+https://github.com/rust-lang/crates.io-index" | 8 | source = "registry+https://github.com/rust-lang/crates.io-index" |
9 | checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" | 9 | checksum = "03345e98af8f3d786b6d9f656ccfa6ac316d954e92bc4841f0bba20789d5fb5a" |
10 | dependencies = [ | 10 | dependencies = [ |
11 | "gimli", | 11 | "gimli", |
12 | ] | 12 | ] |
@@ -72,9 +72,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" | |||
72 | 72 | ||
73 | [[package]] | 73 | [[package]] |
74 | name = "backtrace" | 74 | name = "backtrace" |
75 | version = "0.3.58" | 75 | version = "0.3.59" |
76 | source = "registry+https://github.com/rust-lang/crates.io-index" | 76 | source = "registry+https://github.com/rust-lang/crates.io-index" |
77 | checksum = "88fb5a785d6b44fd9d6700935608639af1b8356de1e55d5f7c2740f4faa15d82" | 77 | checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" |
78 | dependencies = [ | 78 | dependencies = [ |
79 | "addr2line", | 79 | "addr2line", |
80 | "cc", | 80 | "cc", |
@@ -169,9 +169,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
169 | 169 | ||
170 | [[package]] | 170 | [[package]] |
171 | name = "chalk-derive" | 171 | name = "chalk-derive" |
172 | version = "0.64.0" | 172 | version = "0.67.0" |
173 | source = "registry+https://github.com/rust-lang/crates.io-index" | 173 | source = "registry+https://github.com/rust-lang/crates.io-index" |
174 | checksum = "d9acf2a9eab79ae7d44cd77ad86a8b1569d7a5e6d9a7db4a0a57a7344dd82c24" | 174 | checksum = "751a3cd9eeb24d7165e9f90daf1f10a23ffa16a7986f349027f8dfb60f51ee0c" |
175 | dependencies = [ | 175 | dependencies = [ |
176 | "proc-macro2", | 176 | "proc-macro2", |
177 | "quote", | 177 | "quote", |
@@ -181,9 +181,9 @@ dependencies = [ | |||
181 | 181 | ||
182 | [[package]] | 182 | [[package]] |
183 | name = "chalk-ir" | 183 | name = "chalk-ir" |
184 | version = "0.64.0" | 184 | version = "0.67.0" |
185 | source = "registry+https://github.com/rust-lang/crates.io-index" | 185 | source = "registry+https://github.com/rust-lang/crates.io-index" |
186 | checksum = "877661627f54ba3666a72943c43b326cb170d60899e50a8426111e7a657ff032" | 186 | checksum = "4236da905504740d3f72cc8f0509aa01321cc236208e2c33b55eda2db74bc495" |
187 | dependencies = [ | 187 | dependencies = [ |
188 | "bitflags", | 188 | "bitflags", |
189 | "chalk-derive", | 189 | "chalk-derive", |
@@ -192,9 +192,9 @@ dependencies = [ | |||
192 | 192 | ||
193 | [[package]] | 193 | [[package]] |
194 | name = "chalk-recursive" | 194 | name = "chalk-recursive" |
195 | version = "0.64.0" | 195 | version = "0.67.0" |
196 | source = "registry+https://github.com/rust-lang/crates.io-index" | 196 | source = "registry+https://github.com/rust-lang/crates.io-index" |
197 | checksum = "072ffcf17243c2aa3e4b9ea6de3d29e7ef64cfdb0ceccaa431965070a1dc1475" | 197 | checksum = "7d0b123fe45a34c4cd5cb329650a0d163525d2acbe9d754a4538d3340884002e" |
198 | dependencies = [ | 198 | dependencies = [ |
199 | "chalk-derive", | 199 | "chalk-derive", |
200 | "chalk-ir", | 200 | "chalk-ir", |
@@ -205,9 +205,9 @@ dependencies = [ | |||
205 | 205 | ||
206 | [[package]] | 206 | [[package]] |
207 | name = "chalk-solve" | 207 | name = "chalk-solve" |
208 | version = "0.64.0" | 208 | version = "0.67.0" |
209 | source = "registry+https://github.com/rust-lang/crates.io-index" | 209 | source = "registry+https://github.com/rust-lang/crates.io-index" |
210 | checksum = "97d4920c9ef2b26dd0b98ffdf070e27fa31e0b6f637463132083cee597e3d326" | 210 | checksum = "9c54788f0ae3b38e2bb2266f395d462d988c64f92dbd55c68219908fd1ce7ddc" |
211 | dependencies = [ | 211 | dependencies = [ |
212 | "chalk-derive", | 212 | "chalk-derive", |
213 | "chalk-ir", | 213 | "chalk-ir", |
@@ -452,9 +452,9 @@ checksum = "e398fae362f4124bbe630d99519fb2d68a03e2e3a23b441028cdcdc4f4895687" | |||
452 | 452 | ||
453 | [[package]] | 453 | [[package]] |
454 | name = "gimli" | 454 | name = "gimli" |
455 | version = "0.23.0" | 455 | version = "0.24.0" |
456 | source = "registry+https://github.com/rust-lang/crates.io-index" | 456 | source = "registry+https://github.com/rust-lang/crates.io-index" |
457 | checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" | 457 | checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" |
458 | 458 | ||
459 | [[package]] | 459 | [[package]] |
460 | name = "hashbrown" | 460 | name = "hashbrown" |
@@ -715,9 +715,9 @@ dependencies = [ | |||
715 | 715 | ||
716 | [[package]] | 716 | [[package]] |
717 | name = "inotify" | 717 | name = "inotify" |
718 | version = "0.9.2" | 718 | version = "0.9.3" |
719 | source = "registry+https://github.com/rust-lang/crates.io-index" | 719 | source = "registry+https://github.com/rust-lang/crates.io-index" |
720 | checksum = "d19f57db1baad9d09e43a3cd76dcf82ebdafd37d75c9498b87762dba77c93f15" | 720 | checksum = "b031475cb1b103ee221afb806a23d35e0570bf7271d7588762ceba8127ed43b3" |
721 | dependencies = [ | 721 | dependencies = [ |
722 | "bitflags", | 722 | "bitflags", |
723 | "inotify-sys", | 723 | "inotify-sys", |
@@ -830,9 +830,9 @@ dependencies = [ | |||
830 | 830 | ||
831 | [[package]] | 831 | [[package]] |
832 | name = "lsp-types" | 832 | name = "lsp-types" |
833 | version = "0.89.0" | 833 | version = "0.89.1" |
834 | source = "registry+https://github.com/rust-lang/crates.io-index" | 834 | source = "registry+https://github.com/rust-lang/crates.io-index" |
835 | checksum = "07731ecd4ee0654728359a5b95e2a254c857876c04b85225496a35d60345daa7" | 835 | checksum = "48b8a871b0a450bcec0e26d74a59583c8173cb9fb7d7f98889e18abb84838e0f" |
836 | dependencies = [ | 836 | dependencies = [ |
837 | "bitflags", | 837 | "bitflags", |
838 | "serde", | 838 | "serde", |
@@ -995,9 +995,9 @@ dependencies = [ | |||
995 | 995 | ||
996 | [[package]] | 996 | [[package]] |
997 | name = "object" | 997 | name = "object" |
998 | version = "0.23.0" | 998 | version = "0.24.0" |
999 | source = "registry+https://github.com/rust-lang/crates.io-index" | 999 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1000 | checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" | 1000 | checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" |
1001 | 1001 | ||
1002 | [[package]] | 1002 | [[package]] |
1003 | name = "once_cell" | 1003 | name = "once_cell" |
@@ -1124,9 +1124,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" | |||
1124 | 1124 | ||
1125 | [[package]] | 1125 | [[package]] |
1126 | name = "proc-macro2" | 1126 | name = "proc-macro2" |
1127 | version = "1.0.26" | 1127 | version = "1.0.27" |
1128 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1129 | checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" | 1129 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" |
1130 | dependencies = [ | 1130 | dependencies = [ |
1131 | "unicode-xid", | 1131 | "unicode-xid", |
1132 | ] | 1132 | ] |
@@ -1235,9 +1235,9 @@ dependencies = [ | |||
1235 | 1235 | ||
1236 | [[package]] | 1236 | [[package]] |
1237 | name = "rayon" | 1237 | name = "rayon" |
1238 | version = "1.5.0" | 1238 | version = "1.5.1" |
1239 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1240 | checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" | 1240 | checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" |
1241 | dependencies = [ | 1241 | dependencies = [ |
1242 | "autocfg", | 1242 | "autocfg", |
1243 | "crossbeam-deque", | 1243 | "crossbeam-deque", |
@@ -1247,9 +1247,9 @@ dependencies = [ | |||
1247 | 1247 | ||
1248 | [[package]] | 1248 | [[package]] |
1249 | name = "rayon-core" | 1249 | name = "rayon-core" |
1250 | version = "1.9.0" | 1250 | version = "1.9.1" |
1251 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1252 | checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" | 1252 | checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" |
1253 | dependencies = [ | 1253 | dependencies = [ |
1254 | "crossbeam-channel", | 1254 | "crossbeam-channel", |
1255 | "crossbeam-deque", | 1255 | "crossbeam-deque", |
@@ -1260,18 +1260,18 @@ dependencies = [ | |||
1260 | 1260 | ||
1261 | [[package]] | 1261 | [[package]] |
1262 | name = "redox_syscall" | 1262 | name = "redox_syscall" |
1263 | version = "0.2.7" | 1263 | version = "0.2.8" |
1264 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1265 | checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" | 1265 | checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" |
1266 | dependencies = [ | 1266 | dependencies = [ |
1267 | "bitflags", | 1267 | "bitflags", |
1268 | ] | 1268 | ] |
1269 | 1269 | ||
1270 | [[package]] | 1270 | [[package]] |
1271 | name = "regex" | 1271 | name = "regex" |
1272 | version = "1.5.3" | 1272 | version = "1.5.4" |
1273 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1274 | checksum = "ce5f1ceb7f74abbce32601642fcf8e8508a8a8991e0621c7d750295b9095702b" | 1274 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" |
1275 | dependencies = [ | 1275 | dependencies = [ |
1276 | "regex-syntax", | 1276 | "regex-syntax", |
1277 | ] | 1277 | ] |
@@ -1359,18 +1359,18 @@ dependencies = [ | |||
1359 | 1359 | ||
1360 | [[package]] | 1360 | [[package]] |
1361 | name = "rustc-ap-rustc_lexer" | 1361 | name = "rustc-ap-rustc_lexer" |
1362 | version = "716.0.0" | 1362 | version = "720.0.0" |
1363 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1363 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1364 | checksum = "12eac7554c1d3f49f105f14d53c0f3402220e875983113562701d8e597a0995c" | 1364 | checksum = "a025b453b0ae85335336f991f920ca9af5c0dc851171cb9035a16cea5619e9b2" |
1365 | dependencies = [ | 1365 | dependencies = [ |
1366 | "unicode-xid", | 1366 | "unicode-xid", |
1367 | ] | 1367 | ] |
1368 | 1368 | ||
1369 | [[package]] | 1369 | [[package]] |
1370 | name = "rustc-demangle" | 1370 | name = "rustc-demangle" |
1371 | version = "0.1.18" | 1371 | version = "0.1.19" |
1372 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1373 | checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" | 1373 | checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" |
1374 | 1374 | ||
1375 | [[package]] | 1375 | [[package]] |
1376 | name = "rustc-hash" | 1376 | name = "rustc-hash" |
@@ -1455,18 +1455,18 @@ dependencies = [ | |||
1455 | 1455 | ||
1456 | [[package]] | 1456 | [[package]] |
1457 | name = "serde" | 1457 | name = "serde" |
1458 | version = "1.0.125" | 1458 | version = "1.0.126" |
1459 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1460 | checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" | 1460 | checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" |
1461 | dependencies = [ | 1461 | dependencies = [ |
1462 | "serde_derive", | 1462 | "serde_derive", |
1463 | ] | 1463 | ] |
1464 | 1464 | ||
1465 | [[package]] | 1465 | [[package]] |
1466 | name = "serde_derive" | 1466 | name = "serde_derive" |
1467 | version = "1.0.125" | 1467 | version = "1.0.126" |
1468 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1469 | checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" | 1469 | checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" |
1470 | dependencies = [ | 1470 | dependencies = [ |
1471 | "proc-macro2", | 1471 | "proc-macro2", |
1472 | "quote", | 1472 | "quote", |
@@ -1496,9 +1496,9 @@ dependencies = [ | |||
1496 | 1496 | ||
1497 | [[package]] | 1497 | [[package]] |
1498 | name = "serde_repr" | 1498 | name = "serde_repr" |
1499 | version = "0.1.6" | 1499 | version = "0.1.7" |
1500 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1500 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1501 | checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" | 1501 | checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" |
1502 | dependencies = [ | 1502 | dependencies = [ |
1503 | "proc-macro2", | 1503 | "proc-macro2", |
1504 | "quote", | 1504 | "quote", |
@@ -1548,9 +1548,9 @@ dependencies = [ | |||
1548 | 1548 | ||
1549 | [[package]] | 1549 | [[package]] |
1550 | name = "syn" | 1550 | name = "syn" |
1551 | version = "1.0.71" | 1551 | version = "1.0.72" |
1552 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1553 | checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373" | 1553 | checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" |
1554 | dependencies = [ | 1554 | dependencies = [ |
1555 | "proc-macro2", | 1555 | "proc-macro2", |
1556 | "quote", | 1556 | "quote", |
@@ -1848,9 +1848,9 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" | |||
1848 | 1848 | ||
1849 | [[package]] | 1849 | [[package]] |
1850 | name = "url" | 1850 | name = "url" |
1851 | version = "2.2.1" | 1851 | version = "2.2.2" |
1852 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1853 | checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" | 1853 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" |
1854 | dependencies = [ | 1854 | dependencies = [ |
1855 | "form_urlencoded", | 1855 | "form_urlencoded", |
1856 | "idna", | 1856 | "idna", |
@@ -1957,18 +1957,18 @@ dependencies = [ | |||
1957 | 1957 | ||
1958 | [[package]] | 1958 | [[package]] |
1959 | name = "xshell" | 1959 | name = "xshell" |
1960 | version = "0.1.10" | 1960 | version = "0.1.13" |
1961 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1962 | checksum = "aa25217c682f9f991d7889238a99e65eb8431c266d36e0f4e850a73773415473" | 1962 | checksum = "eb15bb1b41eb14efe628006294c294e10c366e03a0283b9c2063fc27d97934c6" |
1963 | dependencies = [ | 1963 | dependencies = [ |
1964 | "xshell-macros", | 1964 | "xshell-macros", |
1965 | ] | 1965 | ] |
1966 | 1966 | ||
1967 | [[package]] | 1967 | [[package]] |
1968 | name = "xshell-macros" | 1968 | name = "xshell-macros" |
1969 | version = "0.1.10" | 1969 | version = "0.1.13" |
1970 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1970 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1971 | checksum = "4404d53d2113af4fa31c58326eb7b37d6d7bf11ba87520787cddeaff45385c72" | 1971 | checksum = "cf7ed94a2c75b9bcc57031229be2b57ee47ba71122f71aabef8610ec66a97e52" |
1972 | 1972 | ||
1973 | [[package]] | 1973 | [[package]] |
1974 | name = "xtask" | 1974 | name = "xtask" |
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 0ef77ef5d..64ccd11ee 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs | |||
@@ -53,11 +53,15 @@ impl SourceRoot { | |||
53 | } | 53 | } |
54 | 54 | ||
55 | /// `CrateGraph` is a bit of information which turns a set of text files into a | 55 | /// `CrateGraph` is a bit of information which turns a set of text files into a |
56 | /// number of Rust crates. Each crate is defined by the `FileId` of its root module, | 56 | /// number of Rust crates. |
57 | /// the set of cfg flags (not yet implemented) and the set of dependencies. Note | 57 | /// |
58 | /// that, due to cfg's, there might be several crates for a single `FileId`! As | 58 | /// Each crate is defined by the `FileId` of its root module, the set of enabled |
59 | /// in the rust-lang proper, a crate does not have a name. Instead, names are | 59 | /// `cfg` flags and the set of dependencies. |
60 | /// specified on dependency edges. That is, a crate might be known under | 60 | /// |
61 | /// Note that, due to cfg's, there might be several crates for a single `FileId`! | ||
62 | /// | ||
63 | /// For the purposes of analysis, a crate does not have a name. Instead, names | ||
64 | /// are specified on dependency edges. That is, a crate might be known under | ||
61 | /// different names in different dependent crates. | 65 | /// different names in different dependent crates. |
62 | /// | 66 | /// |
63 | /// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust | 67 | /// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust |
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 508ac37c2..c5cf803fd 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs | |||
@@ -92,7 +92,7 @@ impl HirDisplay for Function { | |||
92 | &data.ret_type | 92 | &data.ret_type |
93 | } else { | 93 | } else { |
94 | match &*data.ret_type { | 94 | match &*data.ret_type { |
95 | TypeRef::ImplTrait(bounds) => match &bounds[0] { | 95 | TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() { |
96 | TypeBound::Path(path) => { | 96 | TypeBound::Path(path) => { |
97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings | 97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings |
98 | [0] | 98 | [0] |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a7c42ca1e..cdf65a044 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -513,9 +513,8 @@ impl Field { | |||
513 | } | 513 | } |
514 | 514 | ||
515 | /// Returns the type as in the signature of the struct (i.e., with | 515 | /// Returns the type as in the signature of the struct (i.e., with |
516 | /// placeholder types for type parameters). This is good for showing | 516 | /// placeholder types for type parameters). Only use this in the context of |
517 | /// signature help, but not so good to actually get the type of the field | 517 | /// the field definition. |
518 | /// when you actually have a variable of the struct. | ||
519 | pub fn ty(&self, db: &dyn HirDatabase) -> Type { | 518 | pub fn ty(&self, db: &dyn HirDatabase) -> Type { |
520 | let var_id = self.parent.into(); | 519 | let var_id = self.parent.into(); |
521 | let generic_def_id: GenericDefId = match self.parent { | 520 | let generic_def_id: GenericDefId = match self.parent { |
@@ -552,10 +551,6 @@ impl Struct { | |||
552 | Module { id: self.id.lookup(db.upcast()).container } | 551 | Module { id: self.id.lookup(db.upcast()).container } |
553 | } | 552 | } |
554 | 553 | ||
555 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
556 | Some(self.module(db).krate()) | ||
557 | } | ||
558 | |||
559 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 554 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
560 | db.struct_data(self.id).name.clone() | 555 | db.struct_data(self.id).name.clone() |
561 | } | 556 | } |
@@ -640,10 +635,6 @@ impl Enum { | |||
640 | Module { id: self.id.lookup(db.upcast()).container } | 635 | Module { id: self.id.lookup(db.upcast()).container } |
641 | } | 636 | } |
642 | 637 | ||
643 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
644 | Some(self.module(db).krate()) | ||
645 | } | ||
646 | |||
647 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 638 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
648 | db.enum_data(self.id).name.clone() | 639 | db.enum_data(self.id).name.clone() |
649 | } | 640 | } |
@@ -673,6 +664,7 @@ impl Variant { | |||
673 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 664 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
674 | self.parent.module(db) | 665 | self.parent.module(db) |
675 | } | 666 | } |
667 | |||
676 | pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { | 668 | pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { |
677 | self.parent | 669 | self.parent |
678 | } | 670 | } |
@@ -729,10 +721,6 @@ impl Adt { | |||
729 | } | 721 | } |
730 | } | 722 | } |
731 | 723 | ||
732 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
733 | self.module(db).krate() | ||
734 | } | ||
735 | |||
736 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 724 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
737 | match self { | 725 | match self { |
738 | Adt::Struct(s) => s.name(db), | 726 | Adt::Struct(s) => s.name(db), |
@@ -821,10 +809,6 @@ impl Function { | |||
821 | self.id.lookup(db.upcast()).module(db.upcast()).into() | 809 | self.id.lookup(db.upcast()).module(db.upcast()).into() |
822 | } | 810 | } |
823 | 811 | ||
824 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
825 | Some(self.module(db).krate()) | ||
826 | } | ||
827 | |||
828 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 812 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
829 | db.function_data(self.id).name.clone() | 813 | db.function_data(self.id).name.clone() |
830 | } | 814 | } |
@@ -1014,10 +998,6 @@ impl Const { | |||
1014 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 998 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1015 | } | 999 | } |
1016 | 1000 | ||
1017 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
1018 | Some(self.module(db).krate()) | ||
1019 | } | ||
1020 | |||
1021 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 1001 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
1022 | db.const_data(self.id).name.clone() | 1002 | db.const_data(self.id).name.clone() |
1023 | } | 1003 | } |
@@ -1045,10 +1025,6 @@ impl Static { | |||
1045 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1025 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1046 | } | 1026 | } |
1047 | 1027 | ||
1048 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
1049 | Some(self.module(db).krate()) | ||
1050 | } | ||
1051 | |||
1052 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 1028 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
1053 | db.static_data(self.id).name.clone() | 1029 | db.static_data(self.id).name.clone() |
1054 | } | 1030 | } |
@@ -1112,10 +1088,6 @@ impl TypeAlias { | |||
1112 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1088 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1113 | } | 1089 | } |
1114 | 1090 | ||
1115 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
1116 | self.module(db).krate() | ||
1117 | } | ||
1118 | |||
1119 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1091 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1120 | db.type_alias_data(self.id).type_ref.as_deref().cloned() | 1092 | db.type_alias_data(self.id).type_ref.as_deref().cloned() |
1121 | } | 1093 | } |
@@ -1667,10 +1639,6 @@ impl Impl { | |||
1667 | self.id.lookup(db.upcast()).container.into() | 1639 | self.id.lookup(db.upcast()).container.into() |
1668 | } | 1640 | } |
1669 | 1641 | ||
1670 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
1671 | Crate { id: self.module(db).id.krate() } | ||
1672 | } | ||
1673 | |||
1674 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { | 1642 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { |
1675 | let src = self.source(db)?; | 1643 | let src = self.source(db)?; |
1676 | let item = src.file_id.is_builtin_derive(db.upcast())?; | 1644 | let item = src.file_id.is_builtin_derive(db.upcast())?; |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1b5064b5a..8d3c43d08 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -11,7 +11,7 @@ use hir_def::{ | |||
11 | AsMacroCall, FunctionId, TraitId, VariantId, | 11 | AsMacroCall, FunctionId, TraitId, VariantId, |
12 | }; | 12 | }; |
13 | use hir_expand::{name::AsName, ExpansionInfo}; | 13 | use hir_expand::{name::AsName, ExpansionInfo}; |
14 | use hir_ty::associated_type_shorthand_candidates; | 14 | use hir_ty::{associated_type_shorthand_candidates, Interner}; |
15 | use itertools::Itertools; | 15 | use itertools::Itertools; |
16 | use rustc_hash::{FxHashMap, FxHashSet}; | 16 | use rustc_hash::{FxHashMap, FxHashSet}; |
17 | use syntax::{ | 17 | use syntax::{ |
@@ -120,10 +120,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
120 | pub fn speculative_expand( | 120 | pub fn speculative_expand( |
121 | &self, | 121 | &self, |
122 | actual_macro_call: &ast::MacroCall, | 122 | actual_macro_call: &ast::MacroCall, |
123 | hypothetical_args: &ast::TokenTree, | 123 | speculative_args: &ast::TokenTree, |
124 | token_to_map: SyntaxToken, | 124 | token_to_map: SyntaxToken, |
125 | ) -> Option<(SyntaxNode, SyntaxToken)> { | 125 | ) -> Option<(SyntaxNode, SyntaxToken)> { |
126 | self.imp.speculative_expand(actual_macro_call, hypothetical_args, token_to_map) | 126 | self.imp.speculative_expand(actual_macro_call, speculative_args, token_to_map) |
127 | } | 127 | } |
128 | 128 | ||
129 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | 129 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { |
@@ -227,7 +227,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
227 | pub fn resolve_record_field( | 227 | pub fn resolve_record_field( |
228 | &self, | 228 | &self, |
229 | field: &ast::RecordExprField, | 229 | field: &ast::RecordExprField, |
230 | ) -> Option<(Field, Option<Local>)> { | 230 | ) -> Option<(Field, Option<Local>, Type)> { |
231 | self.imp.resolve_record_field(field) | 231 | self.imp.resolve_record_field(field) |
232 | } | 232 | } |
233 | 233 | ||
@@ -335,7 +335,7 @@ impl<'db> SemanticsImpl<'db> { | |||
335 | fn speculative_expand( | 335 | fn speculative_expand( |
336 | &self, | 336 | &self, |
337 | actual_macro_call: &ast::MacroCall, | 337 | actual_macro_call: &ast::MacroCall, |
338 | hypothetical_args: &ast::TokenTree, | 338 | speculative_args: &ast::TokenTree, |
339 | token_to_map: SyntaxToken, | 339 | token_to_map: SyntaxToken, |
340 | ) -> Option<(SyntaxNode, SyntaxToken)> { | 340 | ) -> Option<(SyntaxNode, SyntaxToken)> { |
341 | let sa = self.analyze(actual_macro_call.syntax()); | 341 | let sa = self.analyze(actual_macro_call.syntax()); |
@@ -344,10 +344,10 @@ impl<'db> SemanticsImpl<'db> { | |||
344 | let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { | 344 | let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { |
345 | sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) | 345 | sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) |
346 | })?; | 346 | })?; |
347 | hir_expand::db::expand_hypothetical( | 347 | hir_expand::db::expand_speculative( |
348 | self.db.upcast(), | 348 | self.db.upcast(), |
349 | macro_call_id, | 349 | macro_call_id, |
350 | hypothetical_args, | 350 | speculative_args, |
351 | token_to_map, | 351 | token_to_map, |
352 | ) | 352 | ) |
353 | } | 353 | } |
@@ -501,14 +501,12 @@ impl<'db> SemanticsImpl<'db> { | |||
501 | } | 501 | } |
502 | 502 | ||
503 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { | 503 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { |
504 | self.analyze(call.syntax()).resolve_method_call(self.db, call) | 504 | self.analyze(call.syntax()).resolve_method_call(self.db, call).map(|(id, _)| id) |
505 | } | 505 | } |
506 | 506 | ||
507 | fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { | 507 | fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { |
508 | // FIXME: this erases Substs, we should instead record the correct | 508 | let (func, subst) = self.analyze(call.syntax()).resolve_method_call(self.db, call)?; |
509 | // substitution during inference and use that | 509 | let ty = self.db.value_ty(func.into()).substitute(&Interner, &subst); |
510 | let func = self.resolve_method_call(call)?; | ||
511 | let ty = hir_ty::TyBuilder::value_ty(self.db, func.into()).fill_with_unknown().build(); | ||
512 | let resolver = self.analyze(call.syntax()).resolver; | 510 | let resolver = self.analyze(call.syntax()).resolver; |
513 | let ty = Type::new_with_resolver(self.db, &resolver, ty)?; | 511 | let ty = Type::new_with_resolver(self.db, &resolver, ty)?; |
514 | let mut res = ty.as_callable(self.db)?; | 512 | let mut res = ty.as_callable(self.db)?; |
@@ -520,7 +518,10 @@ impl<'db> SemanticsImpl<'db> { | |||
520 | self.analyze(field.syntax()).resolve_field(self.db, field) | 518 | self.analyze(field.syntax()).resolve_field(self.db, field) |
521 | } | 519 | } |
522 | 520 | ||
523 | fn resolve_record_field(&self, field: &ast::RecordExprField) -> Option<(Field, Option<Local>)> { | 521 | fn resolve_record_field( |
522 | &self, | ||
523 | field: &ast::RecordExprField, | ||
524 | ) -> Option<(Field, Option<Local>, Type)> { | ||
524 | self.analyze(field.syntax()).resolve_record_field(self.db, field) | 525 | self.analyze(field.syntax()).resolve_record_field(self.db, field) |
525 | } | 526 | } |
526 | 527 | ||
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 20753314d..3f940124c 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -143,7 +143,7 @@ impl SourceAnalyzer { | |||
143 | &self, | 143 | &self, |
144 | db: &dyn HirDatabase, | 144 | db: &dyn HirDatabase, |
145 | call: &ast::MethodCallExpr, | 145 | call: &ast::MethodCallExpr, |
146 | ) -> Option<FunctionId> { | 146 | ) -> Option<(FunctionId, Substitution)> { |
147 | let expr_id = self.expr_id(db, &call.clone().into())?; | 147 | let expr_id = self.expr_id(db, &call.clone().into())?; |
148 | self.infer.as_ref()?.method_resolution(expr_id) | 148 | self.infer.as_ref()?.method_resolution(expr_id) |
149 | } | 149 | } |
@@ -161,7 +161,7 @@ impl SourceAnalyzer { | |||
161 | &self, | 161 | &self, |
162 | db: &dyn HirDatabase, | 162 | db: &dyn HirDatabase, |
163 | field: &ast::RecordExprField, | 163 | field: &ast::RecordExprField, |
164 | ) -> Option<(Field, Option<Local>)> { | 164 | ) -> Option<(Field, Option<Local>, Type)> { |
165 | let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; | 165 | let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; |
166 | let expr = ast::Expr::from(record_expr); | 166 | let expr = ast::Expr::from(record_expr); |
167 | let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?; | 167 | let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?; |
@@ -178,10 +178,13 @@ impl SourceAnalyzer { | |||
178 | _ => None, | 178 | _ => None, |
179 | } | 179 | } |
180 | }; | 180 | }; |
181 | let (_, subst) = self.infer.as_ref()?.type_of_expr.get(expr_id)?.as_adt()?; | ||
181 | let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?; | 182 | let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?; |
182 | let variant_data = variant.variant_data(db.upcast()); | 183 | let variant_data = variant.variant_data(db.upcast()); |
183 | let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; | 184 | let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; |
184 | Some((field.into(), local)) | 185 | let field_ty = |
186 | db.field_types(variant).get(field.local_id)?.clone().substitute(&Interner, subst); | ||
187 | Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)?)) | ||
185 | } | 188 | } |
186 | 189 | ||
187 | pub(crate) fn resolve_record_pat_field( | 190 | pub(crate) fn resolve_record_pat_field( |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 89a1ea770..385ba8c80 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -105,7 +105,7 @@ impl RawAttrs { | |||
105 | Either::Left(attr) => Attr::from_src(db, attr, hygiene, id), | 105 | Either::Left(attr) => Attr::from_src(db, attr, hygiene, id), |
106 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { | 106 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { |
107 | id, | 107 | id, |
108 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | 108 | input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))), |
109 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), | 109 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), |
110 | }), | 110 | }), |
111 | }) | 111 | }) |
@@ -151,7 +151,7 @@ impl RawAttrs { | |||
151 | return smallvec![attr.clone()]; | 151 | return smallvec![attr.clone()]; |
152 | } | 152 | } |
153 | 153 | ||
154 | let subtree = match &attr.input { | 154 | let subtree = match attr.input.as_deref() { |
155 | Some(AttrInput::TokenTree(it)) => it, | 155 | Some(AttrInput::TokenTree(it)) => it, |
156 | _ => return smallvec![attr.clone()], | 156 | _ => return smallvec![attr.clone()], |
157 | }; | 157 | }; |
@@ -251,7 +251,7 @@ impl Attrs { | |||
251 | } | 251 | } |
252 | 252 | ||
253 | pub fn docs(&self) -> Option<Documentation> { | 253 | pub fn docs(&self) -> Option<Documentation> { |
254 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { | 254 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? { |
255 | AttrInput::Literal(s) => Some(s), | 255 | AttrInput::Literal(s) => Some(s), |
256 | AttrInput::TokenTree(_) => None, | 256 | AttrInput::TokenTree(_) => None, |
257 | }); | 257 | }); |
@@ -454,7 +454,7 @@ impl AttrsWithOwner { | |||
454 | db: &dyn DefDatabase, | 454 | db: &dyn DefDatabase, |
455 | ) -> Option<(Documentation, DocsRangeMap)> { | 455 | ) -> Option<(Documentation, DocsRangeMap)> { |
456 | // FIXME: code duplication in `docs` above | 456 | // FIXME: code duplication in `docs` above |
457 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { | 457 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? { |
458 | AttrInput::Literal(s) => Some((s, attr.id)), | 458 | AttrInput::Literal(s) => Some((s, attr.id)), |
459 | AttrInput::TokenTree(_) => None, | 459 | AttrInput::TokenTree(_) => None, |
460 | }); | 460 | }); |
@@ -637,10 +637,10 @@ pub(crate) struct AttrId { | |||
637 | pub struct Attr { | 637 | pub struct Attr { |
638 | pub(crate) id: AttrId, | 638 | pub(crate) id: AttrId, |
639 | pub(crate) path: Interned<ModPath>, | 639 | pub(crate) path: Interned<ModPath>, |
640 | pub(crate) input: Option<AttrInput>, | 640 | pub(crate) input: Option<Interned<AttrInput>>, |
641 | } | 641 | } |
642 | 642 | ||
643 | #[derive(Debug, Clone, PartialEq, Eq)] | 643 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
644 | pub enum AttrInput { | 644 | pub enum AttrInput { |
645 | /// `#[attr = "string"]` | 645 | /// `#[attr = "string"]` |
646 | Literal(SmolStr), | 646 | Literal(SmolStr), |
@@ -670,9 +670,9 @@ impl Attr { | |||
670 | ast::LiteralKind::String(string) => string.value()?.into(), | 670 | ast::LiteralKind::String(string) => string.value()?.into(), |
671 | _ => lit.syntax().first_token()?.text().trim_matches('"').into(), | 671 | _ => lit.syntax().first_token()?.text().trim_matches('"').into(), |
672 | }; | 672 | }; |
673 | Some(AttrInput::Literal(value)) | 673 | Some(Interned::new(AttrInput::Literal(value))) |
674 | } else if let Some(tt) = ast.token_tree() { | 674 | } else if let Some(tt) = ast.token_tree() { |
675 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0)) | 675 | Some(Interned::new(AttrInput::TokenTree(ast_to_token_tree(&tt).0))) |
676 | } else { | 676 | } else { |
677 | None | 677 | None |
678 | }; | 678 | }; |
@@ -688,7 +688,7 @@ impl Attr { | |||
688 | return None; | 688 | return None; |
689 | } | 689 | } |
690 | 690 | ||
691 | match &self.input { | 691 | match self.input.as_deref() { |
692 | Some(AttrInput::TokenTree(args)) => { | 692 | Some(AttrInput::TokenTree(args)) => { |
693 | let mut counter = 0; | 693 | let mut counter = 0; |
694 | let paths = args | 694 | let paths = args |
@@ -720,7 +720,7 @@ impl Attr { | |||
720 | } | 720 | } |
721 | 721 | ||
722 | pub fn string_value(&self) -> Option<&SmolStr> { | 722 | pub fn string_value(&self) -> Option<&SmolStr> { |
723 | match self.input.as_ref()? { | 723 | match self.input.as_deref()? { |
724 | AttrInput::Literal(it) => Some(it), | 724 | AttrInput::Literal(it) => Some(it), |
725 | _ => None, | 725 | _ => None, |
726 | } | 726 | } |
@@ -735,14 +735,14 @@ pub struct AttrQuery<'a> { | |||
735 | 735 | ||
736 | impl<'a> AttrQuery<'a> { | 736 | impl<'a> AttrQuery<'a> { |
737 | pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> { | 737 | pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> { |
738 | self.attrs().filter_map(|attr| match attr.input.as_ref()? { | 738 | self.attrs().filter_map(|attr| match attr.input.as_deref()? { |
739 | AttrInput::TokenTree(it) => Some(it), | 739 | AttrInput::TokenTree(it) => Some(it), |
740 | _ => None, | 740 | _ => None, |
741 | }) | 741 | }) |
742 | } | 742 | } |
743 | 743 | ||
744 | pub fn string_value(self) -> Option<&'a SmolStr> { | 744 | pub fn string_value(self) -> Option<&'a SmolStr> { |
745 | self.attrs().find_map(|attr| match attr.input.as_ref()? { | 745 | self.attrs().find_map(|attr| match attr.input.as_deref()? { |
746 | AttrInput::Literal(it) => Some(it), | 746 | AttrInput::Literal(it) => Some(it), |
747 | _ => None, | 747 | _ => None, |
748 | }) | 748 | }) |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 135a6698e..8bcac60ef 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -112,7 +112,7 @@ pub struct TypeAliasData { | |||
112 | pub visibility: RawVisibility, | 112 | pub visibility: RawVisibility, |
113 | pub is_extern: bool, | 113 | pub is_extern: bool, |
114 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). | 114 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). |
115 | pub bounds: Vec<TypeBound>, | 115 | pub bounds: Vec<Interned<TypeBound>>, |
116 | } | 116 | } |
117 | 117 | ||
118 | impl TypeAliasData { | 118 | impl TypeAliasData { |
@@ -141,7 +141,7 @@ pub struct TraitData { | |||
141 | pub is_auto: bool, | 141 | pub is_auto: bool, |
142 | pub is_unsafe: bool, | 142 | pub is_unsafe: bool, |
143 | pub visibility: RawVisibility, | 143 | pub visibility: RawVisibility, |
144 | pub bounds: Box<[TypeBound]>, | 144 | pub bounds: Box<[Interned<TypeBound>]>, |
145 | } | 145 | } |
146 | 146 | ||
147 | impl TraitData { | 147 | impl TraitData { |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index de5acced8..44d22b918 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -68,9 +68,19 @@ pub struct GenericParams { | |||
68 | /// associated type bindings like `Iterator<Item = u32>`. | 68 | /// associated type bindings like `Iterator<Item = u32>`. |
69 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 69 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
70 | pub enum WherePredicate { | 70 | pub enum WherePredicate { |
71 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, | 71 | TypeBound { |
72 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, | 72 | target: WherePredicateTypeTarget, |
73 | ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, | 73 | bound: Interned<TypeBound>, |
74 | }, | ||
75 | Lifetime { | ||
76 | target: LifetimeRef, | ||
77 | bound: LifetimeRef, | ||
78 | }, | ||
79 | ForLifetime { | ||
80 | lifetimes: Box<[Name]>, | ||
81 | target: WherePredicateTypeTarget, | ||
82 | bound: Interned<TypeBound>, | ||
83 | }, | ||
74 | } | 84 | } |
75 | 85 | ||
76 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 86 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -339,11 +349,11 @@ impl GenericParams { | |||
339 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { | 349 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { |
340 | lifetimes: hrtb_lifetimes.clone(), | 350 | lifetimes: hrtb_lifetimes.clone(), |
341 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), | 351 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
342 | bound, | 352 | bound: Interned::new(bound), |
343 | }, | 353 | }, |
344 | None => WherePredicate::TypeBound { | 354 | None => WherePredicate::TypeBound { |
345 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), | 355 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
346 | bound, | 356 | bound: Interned::new(bound), |
347 | }, | 357 | }, |
348 | }, | 358 | }, |
349 | (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { | 359 | (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { |
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index 5cc7f2df6..79ba970e7 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs | |||
@@ -216,7 +216,10 @@ pub use crate::_impl_internable as impl_internable; | |||
216 | impl_internable!( | 216 | impl_internable!( |
217 | crate::type_ref::TypeRef, | 217 | crate::type_ref::TypeRef, |
218 | crate::type_ref::TraitRef, | 218 | crate::type_ref::TraitRef, |
219 | crate::type_ref::TypeBound, | ||
219 | crate::path::ModPath, | 220 | crate::path::ModPath, |
221 | crate::path::GenericArgs, | ||
222 | crate::attr::AttrInput, | ||
220 | GenericParams, | 223 | GenericParams, |
221 | str, | 224 | str, |
222 | ); | 225 | ); |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 528270d49..11767d100 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -1,4 +1,34 @@ | |||
1 | //! A simplified AST that only contains items. | 1 | //! A simplified AST that only contains items. |
2 | //! | ||
3 | //! This is the primary IR used throughout `hir_def`. It is the input to the name resolution | ||
4 | //! algorithm, as well as to the queries defined in `adt.rs`, `data.rs`, and most things in | ||
5 | //! `attr.rs`. | ||
6 | //! | ||
7 | //! `ItemTree`s are built per `HirFileId`, from the syntax tree of the parsed file. This means that | ||
8 | //! they are crate-independent: they don't know which `#[cfg]`s are active or which module they | ||
9 | //! belong to, since those concepts don't exist at this level (a single `ItemTree` might be part of | ||
10 | //! multiple crates, or might be included into the same crate twice via `#[path]`). | ||
11 | //! | ||
12 | //! One important purpose of this layer is to provide an "invalidation barrier" for incremental | ||
13 | //! computations: when typing inside an item body, the `ItemTree` of the modified file is typically | ||
14 | //! unaffected, so we don't have to recompute name resolution results or item data (see `data.rs`). | ||
15 | //! | ||
16 | //! The `ItemTree` for the currently open file can be displayed by using the VS Code command | ||
17 | //! "Rust Analyzer: Debug ItemTree". | ||
18 | //! | ||
19 | //! Compared to rustc's architecture, `ItemTree` has properties from both rustc's AST and HIR: many | ||
20 | //! syntax-level Rust features are already desugared to simpler forms in the `ItemTree`, but name | ||
21 | //! resolution has not yet been performed. `ItemTree`s are per-file, while rustc's AST and HIR are | ||
22 | //! per-crate, because we are interested in incrementally computing it. | ||
23 | //! | ||
24 | //! The representation of items in the `ItemTree` should generally mirror the surface syntax: it is | ||
25 | //! usually a bad idea to desugar a syntax-level construct to something that is structurally | ||
26 | //! different here. Name resolution needs to be able to process attributes and expand macros | ||
27 | //! (including attribute macros), and having a 1-to-1 mapping between syntax and the `ItemTree` | ||
28 | //! avoids introducing subtle bugs. | ||
29 | //! | ||
30 | //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its | ||
31 | //! surface syntax. | ||
2 | 32 | ||
3 | mod lower; | 33 | mod lower; |
4 | mod pretty; | 34 | mod pretty; |
@@ -500,8 +530,8 @@ pub struct Import { | |||
500 | pub alias: Option<ImportAlias>, | 530 | pub alias: Option<ImportAlias>, |
501 | pub visibility: RawVisibilityId, | 531 | pub visibility: RawVisibilityId, |
502 | pub is_glob: bool, | 532 | pub is_glob: bool, |
503 | /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many | 533 | /// AST ID of the `use` item this import was derived from. Note that many `Import`s can map to |
504 | /// `Import`s can map to the same `use` item. | 534 | /// the same `use` item. |
505 | pub ast_id: FileAstId<ast::Use>, | 535 | pub ast_id: FileAstId<ast::Use>, |
506 | /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`. | 536 | /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`. |
507 | /// | 537 | /// |
@@ -614,7 +644,7 @@ pub struct Trait { | |||
614 | pub generic_params: Interned<GenericParams>, | 644 | pub generic_params: Interned<GenericParams>, |
615 | pub is_auto: bool, | 645 | pub is_auto: bool, |
616 | pub is_unsafe: bool, | 646 | pub is_unsafe: bool, |
617 | pub bounds: Box<[TypeBound]>, | 647 | pub bounds: Box<[Interned<TypeBound>]>, |
618 | pub items: Box<[AssocItem]>, | 648 | pub items: Box<[AssocItem]>, |
619 | pub ast_id: FileAstId<ast::Trait>, | 649 | pub ast_id: FileAstId<ast::Trait>, |
620 | } | 650 | } |
@@ -634,7 +664,7 @@ pub struct TypeAlias { | |||
634 | pub name: Name, | 664 | pub name: Name, |
635 | pub visibility: RawVisibilityId, | 665 | pub visibility: RawVisibilityId, |
636 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 666 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
637 | pub bounds: Box<[TypeBound]>, | 667 | pub bounds: Box<[Interned<TypeBound>]>, |
638 | pub generic_params: Interned<GenericParams>, | 668 | pub generic_params: Interned<GenericParams>, |
639 | pub type_ref: Option<Interned<TypeRef>>, | 669 | pub type_ref: Option<Interned<TypeRef>>, |
640 | pub is_extern: bool, | 670 | pub is_extern: bool, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 91cf75371..b4389371f 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -384,7 +384,7 @@ impl<'a> Ctx<'a> { | |||
384 | 384 | ||
385 | let ret_type = if func.async_token().is_some() { | 385 | let ret_type = if func.async_token().is_some() { |
386 | let future_impl = desugar_future_path(ret_type); | 386 | let future_impl = desugar_future_path(ret_type); |
387 | let ty_bound = TypeBound::Path(future_impl); | 387 | let ty_bound = Interned::new(TypeBound::Path(future_impl)); |
388 | TypeRef::ImplTrait(vec![ty_bound]) | 388 | TypeRef::ImplTrait(vec![ty_bound]) |
389 | } else { | 389 | } else { |
390 | ret_type | 390 | ret_type |
@@ -738,11 +738,12 @@ impl<'a> Ctx<'a> { | |||
738 | Interned::new(generics) | 738 | Interned::new(generics) |
739 | } | 739 | } |
740 | 740 | ||
741 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { | 741 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<Interned<TypeBound>> { |
742 | match node.type_bound_list() { | 742 | match node.type_bound_list() { |
743 | Some(bound_list) => { | 743 | Some(bound_list) => bound_list |
744 | bound_list.bounds().map(|it| TypeBound::from_ast(&self.body_ctx, it)).collect() | 744 | .bounds() |
745 | } | 745 | .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it))) |
746 | .collect(), | ||
746 | None => Vec::new(), | 747 | None => Vec::new(), |
747 | } | 748 | } |
748 | } | 749 | } |
@@ -810,7 +811,7 @@ fn desugar_future_path(orig: TypeRef) -> Path { | |||
810 | let binding = | 811 | let binding = |
811 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; | 812 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; |
812 | last.bindings.push(binding); | 813 | last.bindings.push(binding); |
813 | generic_args.push(Some(Arc::new(last))); | 814 | generic_args.push(Some(Interned::new(last))); |
814 | 815 | ||
815 | Path::from_known_path(path, generic_args) | 816 | Path::from_known_path(path, generic_args) |
816 | } | 817 | } |
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index 4bc87a0e2..9394a5de6 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
@@ -513,13 +513,13 @@ impl<'a> Printer<'a> { | |||
513 | } | 513 | } |
514 | } | 514 | } |
515 | 515 | ||
516 | fn print_type_bounds(&mut self, bounds: &[TypeBound]) { | 516 | fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) { |
517 | for (i, bound) in bounds.iter().enumerate() { | 517 | for (i, bound) in bounds.iter().enumerate() { |
518 | if i != 0 { | 518 | if i != 0 { |
519 | w!(self, " + "); | 519 | w!(self, " + "); |
520 | } | 520 | } |
521 | 521 | ||
522 | match bound { | 522 | match bound.as_ref() { |
523 | TypeBound::Path(path) => self.print_path(path), | 523 | TypeBound::Path(path) => self.print_path(path), |
524 | TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), | 524 | TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), |
525 | TypeBound::Error => w!(self, "{{unknown}}"), | 525 | TypeBound::Error => w!(self, "{{unknown}}"), |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index a82ea5957..70001cac8 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -485,6 +485,14 @@ impl VariantId { | |||
485 | VariantId::UnionId(it) => it.lookup(db).id.file_id(), | 485 | VariantId::UnionId(it) => it.lookup(db).id.file_id(), |
486 | } | 486 | } |
487 | } | 487 | } |
488 | |||
489 | pub fn adt_id(self) -> AdtId { | ||
490 | match self { | ||
491 | VariantId::EnumVariantId(it) => it.parent.into(), | ||
492 | VariantId::StructId(it) => it.into(), | ||
493 | VariantId::UnionId(it) => it.into(), | ||
494 | } | ||
495 | } | ||
488 | } | 496 | } |
489 | 497 | ||
490 | trait Intern { | 498 | trait Intern { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 014ea4de4..2ae740d0e 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -285,7 +285,7 @@ impl DefCollector<'_> { | |||
285 | let registered_name = if *attr_name == hir_expand::name![register_attr] | 285 | let registered_name = if *attr_name == hir_expand::name![register_attr] |
286 | || *attr_name == hir_expand::name![register_tool] | 286 | || *attr_name == hir_expand::name![register_tool] |
287 | { | 287 | { |
288 | match &attr.input { | 288 | match attr.input.as_deref() { |
289 | Some(AttrInput::TokenTree(subtree)) => match &*subtree.token_trees { | 289 | Some(AttrInput::TokenTree(subtree)) => match &*subtree.token_trees { |
290 | [tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(), | 290 | [tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(), |
291 | _ => continue, | 291 | _ => continue, |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 9b8873fd2..45ab9d0ff 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -4,7 +4,6 @@ mod lower; | |||
4 | use std::{ | 4 | use std::{ |
5 | fmt::{self, Display}, | 5 | fmt::{self, Display}, |
6 | iter, | 6 | iter, |
7 | sync::Arc, | ||
8 | }; | 7 | }; |
9 | 8 | ||
10 | use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef}; | 9 | use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef}; |
@@ -136,7 +135,7 @@ pub struct Path { | |||
136 | type_anchor: Option<Interned<TypeRef>>, | 135 | type_anchor: Option<Interned<TypeRef>>, |
137 | mod_path: Interned<ModPath>, | 136 | mod_path: Interned<ModPath>, |
138 | /// Invariant: the same len as `self.mod_path.segments` | 137 | /// Invariant: the same len as `self.mod_path.segments` |
139 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 138 | generic_args: Vec<Option<Interned<GenericArgs>>>, |
140 | } | 139 | } |
141 | 140 | ||
142 | /// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This | 141 | /// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This |
@@ -165,7 +164,7 @@ pub struct AssociatedTypeBinding { | |||
165 | /// Bounds for the associated type, like in `Iterator<Item: | 164 | /// Bounds for the associated type, like in `Iterator<Item: |
166 | /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` | 165 | /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` |
167 | /// feature.) | 166 | /// feature.) |
168 | pub bounds: Vec<TypeBound>, | 167 | pub bounds: Vec<Interned<TypeBound>>, |
169 | } | 168 | } |
170 | 169 | ||
171 | /// A single generic argument. | 170 | /// A single generic argument. |
@@ -185,7 +184,7 @@ impl Path { | |||
185 | /// Converts a known mod path to `Path`. | 184 | /// Converts a known mod path to `Path`. |
186 | pub(crate) fn from_known_path( | 185 | pub(crate) fn from_known_path( |
187 | path: ModPath, | 186 | path: ModPath, |
188 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 187 | generic_args: Vec<Option<Interned<GenericArgs>>>, |
189 | ) -> Path { | 188 | ) -> Path { |
190 | Path { type_anchor: None, mod_path: Interned::new(path), generic_args } | 189 | Path { type_anchor: None, mod_path: Interned::new(path), generic_args } |
191 | } | 190 | } |
@@ -239,7 +238,7 @@ pub struct PathSegment<'a> { | |||
239 | 238 | ||
240 | pub struct PathSegments<'a> { | 239 | pub struct PathSegments<'a> { |
241 | segments: &'a [Name], | 240 | segments: &'a [Name], |
242 | generic_args: &'a [Option<Arc<GenericArgs>>], | 241 | generic_args: &'a [Option<Interned<GenericArgs>>], |
243 | } | 242 | } |
244 | 243 | ||
245 | impl<'a> PathSegments<'a> { | 244 | impl<'a> PathSegments<'a> { |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index a873325b2..5d5dd9c8f 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -3,7 +3,6 @@ | |||
3 | mod lower_use; | 3 | mod lower_use; |
4 | 4 | ||
5 | use crate::intern::Interned; | 5 | use crate::intern::Interned; |
6 | use std::sync::Arc; | ||
7 | 6 | ||
8 | use either::Either; | 7 | use either::Either; |
9 | use hir_expand::name::{name, AsName}; | 8 | use hir_expand::name::{name, AsName}; |
@@ -48,7 +47,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> { | |||
48 | segment.ret_type(), | 47 | segment.ret_type(), |
49 | ) | 48 | ) |
50 | }) | 49 | }) |
51 | .map(Arc::new); | 50 | .map(Interned::new); |
52 | segments.push(name); | 51 | segments.push(name); |
53 | generic_args.push(args) | 52 | generic_args.push(args) |
54 | } | 53 | } |
@@ -87,13 +86,13 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> { | |||
87 | // Insert the type reference (T in the above example) as Self parameter for the trait | 86 | // Insert the type reference (T in the above example) as Self parameter for the trait |
88 | let last_segment = | 87 | let last_segment = |
89 | generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; | 88 | generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; |
90 | if last_segment.is_none() { | 89 | let mut args_inner = match last_segment { |
91 | *last_segment = Some(Arc::new(GenericArgs::empty())); | 90 | Some(it) => it.as_ref().clone(), |
91 | None => GenericArgs::empty(), | ||
92 | }; | 92 | }; |
93 | let args = last_segment.as_mut().unwrap(); | ||
94 | let mut args_inner = Arc::make_mut(args); | ||
95 | args_inner.has_self_type = true; | 93 | args_inner.has_self_type = true; |
96 | args_inner.args.insert(0, GenericArg::Type(self_type)); | 94 | args_inner.args.insert(0, GenericArg::Type(self_type)); |
95 | *last_segment = Some(Interned::new(args_inner)); | ||
97 | } | 96 | } |
98 | } | 97 | } |
99 | } | 98 | } |
@@ -171,7 +170,9 @@ pub(super) fn lower_generic_args( | |||
171 | let name = name_ref.as_name(); | 170 | let name = name_ref.as_name(); |
172 | let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); | 171 | let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); |
173 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { | 172 | let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { |
174 | l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() | 173 | l.bounds() |
174 | .map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))) | ||
175 | .collect() | ||
175 | } else { | 176 | } else { |
176 | Vec::new() | 177 | Vec::new() |
177 | }; | 178 | }; |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index cdcab7110..cbde6b940 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -5,7 +5,7 @@ use hir_expand::{name::Name, AstId, InFile}; | |||
5 | use std::convert::TryInto; | 5 | use std::convert::TryInto; |
6 | use syntax::ast; | 6 | use syntax::ast; |
7 | 7 | ||
8 | use crate::{body::LowerCtx, path::Path}; | 8 | use crate::{body::LowerCtx, intern::Interned, path::Path}; |
9 | 9 | ||
10 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 10 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
11 | pub enum Mutability { | 11 | pub enum Mutability { |
@@ -91,8 +91,8 @@ pub enum TypeRef { | |||
91 | /// A fn pointer. Last element of the vector is the return type. | 91 | /// A fn pointer. Last element of the vector is the return type. |
92 | Fn(Vec<TypeRef>, bool /*varargs*/), | 92 | Fn(Vec<TypeRef>, bool /*varargs*/), |
93 | // For | 93 | // For |
94 | ImplTrait(Vec<TypeBound>), | 94 | ImplTrait(Vec<Interned<TypeBound>>), |
95 | DynTrait(Vec<TypeBound>), | 95 | DynTrait(Vec<Interned<TypeBound>>), |
96 | Macro(AstId<ast::MacroCall>), | 96 | Macro(AstId<ast::MacroCall>), |
97 | Error, | 97 | Error, |
98 | } | 98 | } |
@@ -232,7 +232,7 @@ impl TypeRef { | |||
232 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | 232 | | TypeRef::Slice(type_ref) => go(&type_ref, f), |
233 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | 233 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { |
234 | for bound in bounds { | 234 | for bound in bounds { |
235 | match bound { | 235 | match bound.as_ref() { |
236 | TypeBound::Path(path) => go_path(path, f), | 236 | TypeBound::Path(path) => go_path(path, f), |
237 | TypeBound::Lifetime(_) | TypeBound::Error => (), | 237 | TypeBound::Lifetime(_) | TypeBound::Error => (), |
238 | } | 238 | } |
@@ -262,7 +262,7 @@ impl TypeRef { | |||
262 | go(type_ref, f); | 262 | go(type_ref, f); |
263 | } | 263 | } |
264 | for bound in &binding.bounds { | 264 | for bound in &binding.bounds { |
265 | match bound { | 265 | match bound.as_ref() { |
266 | TypeBound::Path(path) => go_path(path, f), | 266 | TypeBound::Path(path) => go_path(path, f), |
267 | TypeBound::Lifetime(_) | TypeBound::Error => (), | 267 | TypeBound::Lifetime(_) | TypeBound::Error => (), |
268 | } | 268 | } |
@@ -277,9 +277,9 @@ impl TypeRef { | |||
277 | pub(crate) fn type_bounds_from_ast( | 277 | pub(crate) fn type_bounds_from_ast( |
278 | lower_ctx: &LowerCtx, | 278 | lower_ctx: &LowerCtx, |
279 | type_bounds_opt: Option<ast::TypeBoundList>, | 279 | type_bounds_opt: Option<ast::TypeBoundList>, |
280 | ) -> Vec<TypeBound> { | 280 | ) -> Vec<Interned<TypeBound>> { |
281 | if let Some(type_bounds) = type_bounds_opt { | 281 | if let Some(type_bounds) = type_bounds_opt { |
282 | type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() | 282 | type_bounds.bounds().map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))).collect() |
283 | } else { | 283 | } else { |
284 | vec![] | 284 | vec![] |
285 | } | 285 | } |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 5c769c1bf..625c26f0a 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -131,15 +131,15 @@ pub trait AstDatabase: SourceDatabase { | |||
131 | /// used for completion, where we want to see what 'would happen' if we insert a | 131 | /// used for completion, where we want to see what 'would happen' if we insert a |
132 | /// token. The `token_to_map` mapped down into the expansion, with the mapped | 132 | /// token. The `token_to_map` mapped down into the expansion, with the mapped |
133 | /// token returned. | 133 | /// token returned. |
134 | pub fn expand_hypothetical( | 134 | pub fn expand_speculative( |
135 | db: &dyn AstDatabase, | 135 | db: &dyn AstDatabase, |
136 | actual_macro_call: MacroCallId, | 136 | actual_macro_call: MacroCallId, |
137 | hypothetical_args: &ast::TokenTree, | 137 | speculative_args: &ast::TokenTree, |
138 | token_to_map: SyntaxToken, | 138 | token_to_map: SyntaxToken, |
139 | ) -> Option<(SyntaxNode, SyntaxToken)> { | 139 | ) -> Option<(SyntaxNode, SyntaxToken)> { |
140 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); | 140 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(speculative_args.syntax()); |
141 | let range = | 141 | let range = |
142 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | 142 | token_to_map.text_range().checked_sub(speculative_args.syntax().text_range().start())?; |
143 | let token_id = tmap_1.token_by_range(range)?; | 143 | let token_id = tmap_1.token_by_range(range)?; |
144 | 144 | ||
145 | let macro_def = { | 145 | let macro_def = { |
@@ -147,15 +147,15 @@ pub fn expand_hypothetical( | |||
147 | db.macro_def(loc.def)? | 147 | db.macro_def(loc.def)? |
148 | }; | 148 | }; |
149 | 149 | ||
150 | let hypothetical_expansion = macro_def.expand(db, actual_macro_call, &tt); | 150 | let speculative_expansion = macro_def.expand(db, actual_macro_call, &tt); |
151 | 151 | ||
152 | let fragment_kind = macro_fragment_kind(db, actual_macro_call); | 152 | let fragment_kind = macro_fragment_kind(db, actual_macro_call); |
153 | 153 | ||
154 | let (node, tmap_2) = | 154 | let (node, tmap_2) = |
155 | mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?; | 155 | mbe::token_tree_to_syntax_node(&speculative_expansion.value, fragment_kind).ok()?; |
156 | 156 | ||
157 | let token_id = macro_def.map_id_down(token_id); | 157 | let token_id = macro_def.map_id_down(token_id); |
158 | let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; | 158 | let range = tmap_2.range_by_token(token_id, token_to_map.kind())?; |
159 | let token = node.syntax_node().covering_element(range).into_token()?; | 159 | let token = node.syntax_node().covering_element(range).into_token()?; |
160 | Some((node.syntax_node(), token)) | 160 | Some((node.syntax_node(), token)) |
161 | } | 161 | } |
@@ -325,7 +325,7 @@ fn macro_expand_with_arg( | |||
325 | if let Some(eager) = &loc.eager { | 325 | if let Some(eager) = &loc.eager { |
326 | if arg.is_some() { | 326 | if arg.is_some() { |
327 | return ExpandResult::str_err( | 327 | return ExpandResult::str_err( |
328 | "hypothetical macro expansion not implemented for eager macro".to_owned(), | 328 | "speculative macro expansion not implemented for eager macro".to_owned(), |
329 | ); | 329 | ); |
330 | } else { | 330 | } else { |
331 | return ExpandResult { | 331 | return ExpandResult { |
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 38e09fdd4..d98913907 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -154,7 +154,7 @@ impl HygieneInfo { | |||
154 | }, | 154 | }, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | let range = token_map.range_by_token(token_id)?.by_kind(SyntaxKind::IDENT)?; | 157 | let range = token_map.range_by_token(token_id, SyntaxKind::IDENT)?; |
158 | Some((tt.with_value(range + tt.value), origin)) | 158 | Some((tt.with_value(range + tt.value), origin)) |
159 | } | 159 | } |
160 | } | 160 | } |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 92c679dd2..6be4516a3 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -329,7 +329,7 @@ impl ExpansionInfo { | |||
329 | let token_id = self.macro_arg.1.token_by_range(range)?; | 329 | let token_id = self.macro_arg.1.token_by_range(range)?; |
330 | let token_id = self.macro_def.map_id_down(token_id); | 330 | let token_id = self.macro_def.map_id_down(token_id); |
331 | 331 | ||
332 | let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; | 332 | let range = self.exp_map.range_by_token(token_id, token.value.kind())?; |
333 | 333 | ||
334 | let token = self.expanded.value.covering_element(range).into_token()?; | 334 | let token = self.expanded.value.covering_element(range).into_token()?; |
335 | 335 | ||
@@ -354,7 +354,7 @@ impl ExpansionInfo { | |||
354 | }, | 354 | }, |
355 | }; | 355 | }; |
356 | 356 | ||
357 | let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; | 357 | let range = token_map.range_by_token(token_id, token.value.kind())?; |
358 | let token = | 358 | let token = |
359 | tt.value.covering_element(range + tt.value.text_range().start()).into_token()?; | 359 | tt.value.covering_element(range + tt.value.text_range().start()).into_token()?; |
360 | Some((tt.with_value(token), origin)) | 360 | Some((tt.with_value(token), origin)) |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 66b3418f2..a9994082a 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -18,9 +18,9 @@ ena = "0.14.0" | |||
18 | log = "0.4.8" | 18 | log = "0.4.8" |
19 | rustc-hash = "1.1.0" | 19 | rustc-hash = "1.1.0" |
20 | scoped-tls = "1" | 20 | scoped-tls = "1" |
21 | chalk-solve = { version = "0.64", default-features = false } | 21 | chalk-solve = { version = "0.67", default-features = false } |
22 | chalk-ir = "0.64" | 22 | chalk-ir = "0.67" |
23 | chalk-recursive = "0.64" | 23 | chalk-recursive = "0.67" |
24 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 24 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
25 | 25 | ||
26 | stdx = { path = "../stdx", version = "0.0.0" } | 26 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 53c4ee9da..d1f113e7f 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -181,7 +181,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
181 | for (id, expr) in body.exprs.iter() { | 181 | for (id, expr) in body.exprs.iter() { |
182 | if let Expr::MethodCall { receiver, .. } = expr { | 182 | if let Expr::MethodCall { receiver, .. } = expr { |
183 | let function_id = match self.infer.method_resolution(id) { | 183 | let function_id = match self.infer.method_resolution(id) { |
184 | Some(id) => id, | 184 | Some((id, _)) => id, |
185 | None => continue, | 185 | None => continue, |
186 | }; | 186 | }; |
187 | 187 | ||
@@ -239,15 +239,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
239 | return; | 239 | return; |
240 | } | 240 | } |
241 | 241 | ||
242 | // FIXME: note that we erase information about substs here. This | 242 | let (callee, subst) = match self.infer.method_resolution(call_id) { |
243 | // is not right, but, luckily, doesn't matter as we care only | 243 | Some(it) => it, |
244 | // about the number of params | ||
245 | let callee = match self.infer.method_resolution(call_id) { | ||
246 | Some(callee) => callee, | ||
247 | None => return, | 244 | None => return, |
248 | }; | 245 | }; |
249 | let sig = | 246 | let sig = db.callable_item_signature(callee.into()).substitute(&Interner, &subst); |
250 | db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0; | ||
251 | 247 | ||
252 | (sig, args) | 248 | (sig, args) |
253 | } | 249 | } |
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index ed97dc0e3..5d13bddea 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -105,7 +105,7 @@ fn walk_unsafe( | |||
105 | Expr::MethodCall { .. } => { | 105 | Expr::MethodCall { .. } => { |
106 | if infer | 106 | if infer |
107 | .method_resolution(current) | 107 | .method_resolution(current) |
108 | .map(|func| db.function_data(func).is_unsafe()) | 108 | .map(|(func, _)| db.function_data(func).is_unsafe()) |
109 | .unwrap_or(false) | 109 | .unwrap_or(false) |
110 | { | 110 | { |
111 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 111 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 7bbd1a1f7..637bbc634 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -13,6 +13,7 @@ use hir_def::{ | |||
13 | db::DefDatabase, | 13 | db::DefDatabase, |
14 | find_path, | 14 | find_path, |
15 | generics::TypeParamProvenance, | 15 | generics::TypeParamProvenance, |
16 | intern::{Internable, Interned}, | ||
16 | item_scope::ItemInNs, | 17 | item_scope::ItemInNs, |
17 | path::{Path, PathKind}, | 18 | path::{Path, PathKind}, |
18 | type_ref::{TypeBound, TypeRef}, | 19 | type_ref::{TypeBound, TypeRef}, |
@@ -256,6 +257,12 @@ impl<T: HirDisplay> HirDisplay for &'_ T { | |||
256 | } | 257 | } |
257 | } | 258 | } |
258 | 259 | ||
260 | impl<T: HirDisplay + Internable> HirDisplay for Interned<T> { | ||
261 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
262 | HirDisplay::hir_fmt(self.as_ref(), f) | ||
263 | } | ||
264 | } | ||
265 | |||
259 | impl HirDisplay for ProjectionTy { | 266 | impl HirDisplay for ProjectionTy { |
260 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 267 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
261 | if f.should_truncate() { | 268 | if f.should_truncate() { |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index f1cebbdb9..db3c937ff 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use syntax::SmolStr; | |||
37 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; | 37 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; |
38 | use crate::{ | 38 | use crate::{ |
39 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, | 39 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
40 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder, | 40 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, Substitution, |
41 | TyExt, TyKind, | 41 | TyBuilder, TyExt, TyKind, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | // This lint has a false positive here. See the link below for details. | 44 | // This lint has a false positive here. See the link below for details. |
@@ -132,7 +132,7 @@ impl Default for InternedStandardTypes { | |||
132 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 132 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
133 | pub struct InferenceResult { | 133 | pub struct InferenceResult { |
134 | /// For each method call expr, records the function it resolves to. | 134 | /// For each method call expr, records the function it resolves to. |
135 | method_resolutions: FxHashMap<ExprId, FunctionId>, | 135 | method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>, |
136 | /// For each field access expr, records the field it resolves to. | 136 | /// For each field access expr, records the field it resolves to. |
137 | field_resolutions: FxHashMap<ExprId, FieldId>, | 137 | field_resolutions: FxHashMap<ExprId, FieldId>, |
138 | /// For each struct literal or pattern, records the variant it resolves to. | 138 | /// For each struct literal or pattern, records the variant it resolves to. |
@@ -152,8 +152,8 @@ pub struct InferenceResult { | |||
152 | } | 152 | } |
153 | 153 | ||
154 | impl InferenceResult { | 154 | impl InferenceResult { |
155 | pub fn method_resolution(&self, expr: ExprId) -> Option<FunctionId> { | 155 | pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> { |
156 | self.method_resolutions.get(&expr).copied() | 156 | self.method_resolutions.get(&expr).cloned() |
157 | } | 157 | } |
158 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { | 158 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { |
159 | self.field_resolutions.get(&expr).copied() | 159 | self.field_resolutions.get(&expr).copied() |
@@ -284,14 +284,17 @@ impl<'a> InferenceContext<'a> { | |||
284 | self.table.propagate_diverging_flag(); | 284 | self.table.propagate_diverging_flag(); |
285 | let mut result = std::mem::take(&mut self.result); | 285 | let mut result = std::mem::take(&mut self.result); |
286 | for ty in result.type_of_expr.values_mut() { | 286 | for ty in result.type_of_expr.values_mut() { |
287 | *ty = self.table.resolve_ty_completely(ty.clone()); | 287 | *ty = self.table.resolve_completely(ty.clone()); |
288 | } | 288 | } |
289 | for ty in result.type_of_pat.values_mut() { | 289 | for ty in result.type_of_pat.values_mut() { |
290 | *ty = self.table.resolve_ty_completely(ty.clone()); | 290 | *ty = self.table.resolve_completely(ty.clone()); |
291 | } | 291 | } |
292 | for mismatch in result.type_mismatches.values_mut() { | 292 | for mismatch in result.type_mismatches.values_mut() { |
293 | mismatch.expected = self.table.resolve_ty_completely(mismatch.expected.clone()); | 293 | mismatch.expected = self.table.resolve_completely(mismatch.expected.clone()); |
294 | mismatch.actual = self.table.resolve_ty_completely(mismatch.actual.clone()); | 294 | mismatch.actual = self.table.resolve_completely(mismatch.actual.clone()); |
295 | } | ||
296 | for (_, subst) in result.method_resolutions.values_mut() { | ||
297 | *subst = self.table.resolve_completely(subst.clone()); | ||
295 | } | 298 | } |
296 | result | 299 | result |
297 | } | 300 | } |
@@ -300,8 +303,8 @@ impl<'a> InferenceContext<'a> { | |||
300 | self.result.type_of_expr.insert(expr, ty); | 303 | self.result.type_of_expr.insert(expr, ty); |
301 | } | 304 | } |
302 | 305 | ||
303 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId) { | 306 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) { |
304 | self.result.method_resolutions.insert(expr, func); | 307 | self.result.method_resolutions.insert(expr, (func, subst)); |
305 | } | 308 | } |
306 | 309 | ||
307 | fn write_field_resolution(&mut self, expr: ExprId, field: FieldId) { | 310 | fn write_field_resolution(&mut self, expr: ExprId, field: FieldId) { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 08c05c67c..79a732106 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -805,7 +805,7 @@ impl<'a> InferenceContext<'a> { | |||
805 | None => self.table.new_float_var(), | 805 | None => self.table.new_float_var(), |
806 | }, | 806 | }, |
807 | }, | 807 | }, |
808 | Expr::MacroStmts { tail } => self.infer_expr(*tail, expected), | 808 | Expr::MacroStmts { tail } => self.infer_expr_inner(*tail, expected), |
809 | }; | 809 | }; |
810 | // use a new type variable if we got unknown here | 810 | // use a new type variable if we got unknown here |
811 | let ty = self.insert_type_vars_shallow(ty); | 811 | let ty = self.insert_type_vars_shallow(ty); |
@@ -891,17 +891,21 @@ impl<'a> InferenceContext<'a> { | |||
891 | method_name, | 891 | method_name, |
892 | ) | 892 | ) |
893 | }); | 893 | }); |
894 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 894 | let (derefed_receiver_ty, method_ty, substs) = match resolved { |
895 | Some((ty, func)) => { | 895 | Some((ty, func)) => { |
896 | let ty = canonicalized_receiver.decanonicalize_ty(ty); | 896 | let ty = canonicalized_receiver.decanonicalize_ty(ty); |
897 | self.write_method_resolution(tgt_expr, func); | 897 | let generics = generics(self.db.upcast(), func.into()); |
898 | (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) | 898 | let substs = self.substs_for_method_call(generics, generic_args, &ty); |
899 | self.write_method_resolution(tgt_expr, func, substs.clone()); | ||
900 | (ty, self.db.value_ty(func.into()), substs) | ||
899 | } | 901 | } |
900 | None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None), | 902 | None => ( |
903 | receiver_ty, | ||
904 | Binders::empty(&Interner, self.err_ty()), | ||
905 | Substitution::empty(&Interner), | ||
906 | ), | ||
901 | }; | 907 | }; |
902 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | ||
903 | let method_ty = method_ty.substitute(&Interner, &substs); | 908 | let method_ty = method_ty.substitute(&Interner, &substs); |
904 | let method_ty = self.insert_type_vars(method_ty); | ||
905 | self.register_obligations_for_call(&method_ty); | 909 | self.register_obligations_for_call(&method_ty); |
906 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 910 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
907 | Some(sig) => { | 911 | Some(sig) => { |
@@ -950,23 +954,21 @@ impl<'a> InferenceContext<'a> { | |||
950 | 954 | ||
951 | fn substs_for_method_call( | 955 | fn substs_for_method_call( |
952 | &mut self, | 956 | &mut self, |
953 | def_generics: Option<Generics>, | 957 | def_generics: Generics, |
954 | generic_args: Option<&GenericArgs>, | 958 | generic_args: Option<&GenericArgs>, |
955 | receiver_ty: &Ty, | 959 | receiver_ty: &Ty, |
956 | ) -> Substitution { | 960 | ) -> Substitution { |
957 | let (parent_params, self_params, type_params, impl_trait_params) = | 961 | let (parent_params, self_params, type_params, impl_trait_params) = |
958 | def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split()); | 962 | def_generics.provenance_split(); |
959 | assert_eq!(self_params, 0); // method shouldn't have another Self param | 963 | assert_eq!(self_params, 0); // method shouldn't have another Self param |
960 | let total_len = parent_params + type_params + impl_trait_params; | 964 | let total_len = parent_params + type_params + impl_trait_params; |
961 | let mut substs = Vec::with_capacity(total_len); | 965 | let mut substs = Vec::with_capacity(total_len); |
962 | // Parent arguments are unknown, except for the receiver type | 966 | // Parent arguments are unknown, except for the receiver type |
963 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 967 | for (_id, param) in def_generics.iter_parent() { |
964 | for (_id, param) in parent_generics { | 968 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
965 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { | 969 | substs.push(receiver_ty.clone()); |
966 | substs.push(receiver_ty.clone()); | 970 | } else { |
967 | } else { | 971 | substs.push(self.table.new_type_var()); |
968 | substs.push(self.err_ty()); | ||
969 | } | ||
970 | } | 972 | } |
971 | } | 973 | } |
972 | // handle provided type arguments | 974 | // handle provided type arguments |
@@ -989,7 +991,7 @@ impl<'a> InferenceContext<'a> { | |||
989 | }; | 991 | }; |
990 | let supplied_params = substs.len(); | 992 | let supplied_params = substs.len(); |
991 | for _ in supplied_params..total_len { | 993 | for _ in supplied_params..total_len { |
992 | substs.push(self.err_ty()); | 994 | substs.push(self.table.new_type_var()); |
993 | } | 995 | } |
994 | assert_eq!(substs.len(), total_len); | 996 | assert_eq!(substs.len(), total_len); |
995 | Substitution::from_iter(&Interner, substs) | 997 | Substitution::from_iter(&Interner, substs) |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index f8233cac3..ea5684229 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -295,8 +295,11 @@ impl<'a> InferenceTable<'a> { | |||
295 | .expect("fold failed unexpectedly") | 295 | .expect("fold failed unexpectedly") |
296 | } | 296 | } |
297 | 297 | ||
298 | pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { | 298 | pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T::Result |
299 | self.resolve_with_fallback(ty, |_, _, d, _| d) | 299 | where |
300 | T: HasInterner<Interner = Interner> + Fold<Interner>, | ||
301 | { | ||
302 | self.resolve_with_fallback(t, |_, _, d, _| d) | ||
300 | } | 303 | } |
301 | 304 | ||
302 | /// Unify two types and register new trait goals that arise from that. | 305 | /// Unify two types and register new trait goals that arise from that. |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 8a375b973..c83933c73 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -10,6 +10,7 @@ use std::{iter, sync::Arc}; | |||
10 | 10 | ||
11 | use base_db::CrateId; | 11 | use base_db::CrateId; |
12 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; | 12 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; |
13 | use hir_def::intern::Interned; | ||
13 | use hir_def::{ | 14 | use hir_def::{ |
14 | adt::StructKind, | 15 | adt::StructKind, |
15 | body::{Expander, LowerCtx}, | 16 | body::{Expander, LowerCtx}, |
@@ -843,7 +844,7 @@ impl<'a> TyLoweringContext<'a> { | |||
843 | }) | 844 | }) |
844 | } | 845 | } |
845 | 846 | ||
846 | fn lower_impl_trait(&self, bounds: &[TypeBound]) -> ReturnTypeImplTrait { | 847 | fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>]) -> ReturnTypeImplTrait { |
847 | cov_mark::hit!(lower_rpit); | 848 | cov_mark::hit!(lower_rpit); |
848 | let self_ty = | 849 | let self_ty = |
849 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 850 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
@@ -1025,7 +1026,7 @@ pub(crate) fn trait_environment_query( | |||
1025 | }; | 1026 | }; |
1026 | if let Some(AssocContainerId::TraitId(trait_id)) = container { | 1027 | if let Some(AssocContainerId::TraitId(trait_id)) = container { |
1027 | // add `Self: Trait<T1, T2, ...>` to the environment in trait | 1028 | // add `Self: Trait<T1, T2, ...>` to the environment in trait |
1028 | // function default implementations (and hypothetical code | 1029 | // function default implementations (and speculative code |
1029 | // inside consts or type aliases) | 1030 | // inside consts or type aliases) |
1030 | cov_mark::hit!(trait_self_implements_self); | 1031 | cov_mark::hit!(trait_self_implements_self); |
1031 | let substs = TyBuilder::type_params_subst(db, trait_id); | 1032 | let substs = TyBuilder::type_params_subst(db, trait_id); |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index bb568ea37..6dac7e103 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -832,11 +832,9 @@ fn coerce_unsize_super_trait_cycle() { | |||
832 | ); | 832 | ); |
833 | } | 833 | } |
834 | 834 | ||
835 | #[ignore] | ||
836 | #[test] | 835 | #[test] |
837 | fn coerce_unsize_generic() { | 836 | fn coerce_unsize_generic() { |
838 | // FIXME: Implement this | 837 | // FIXME: fix the type mismatches here |
839 | // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions | ||
840 | check_infer_with_mismatches( | 838 | check_infer_with_mismatches( |
841 | r#" | 839 | r#" |
842 | #[lang = "unsize"] | 840 | #[lang = "unsize"] |
@@ -854,8 +852,58 @@ fn coerce_unsize_generic() { | |||
854 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | 852 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); |
855 | } | 853 | } |
856 | "#, | 854 | "#, |
857 | expect![[r" | 855 | expect![[r#" |
858 | "]], | 856 | 209..317 '{ ... }); }': () |
857 | 219..220 '_': &Foo<[usize]> | ||
858 | 238..259 '&Foo {..., 3] }': &Foo<[usize]> | ||
859 | 239..259 'Foo { ..., 3] }': Foo<[usize]> | ||
860 | 248..257 '[1, 2, 3]': [usize; 3] | ||
861 | 249..250 '1': usize | ||
862 | 252..253 '2': usize | ||
863 | 255..256 '3': usize | ||
864 | 269..270 '_': &Bar<[usize]> | ||
865 | 288..314 '&Bar(F... 3] })': &Bar<[i32; 3]> | ||
866 | 289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]> | ||
867 | 289..314 'Bar(Fo... 3] })': Bar<[i32; 3]> | ||
868 | 293..313 'Foo { ..., 3] }': Foo<[i32; 3]> | ||
869 | 302..311 '[1, 2, 3]': [i32; 3] | ||
870 | 303..304 '1': i32 | ||
871 | 306..307 '2': i32 | ||
872 | 309..310 '3': i32 | ||
873 | 248..257: expected [usize], got [usize; 3] | ||
874 | 288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]> | ||
875 | "#]], | ||
876 | ); | ||
877 | } | ||
878 | |||
879 | #[test] | ||
880 | fn coerce_unsize_apit() { | ||
881 | // FIXME: #8984 | ||
882 | check_infer_with_mismatches( | ||
883 | r#" | ||
884 | #[lang = "sized"] | ||
885 | pub trait Sized {} | ||
886 | #[lang = "unsize"] | ||
887 | pub trait Unsize<T> {} | ||
888 | #[lang = "coerce_unsized"] | ||
889 | pub trait CoerceUnsized<T> {} | ||
890 | |||
891 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
892 | |||
893 | trait Foo {} | ||
894 | |||
895 | fn test(f: impl Foo) { | ||
896 | let _: &dyn Foo = &f; | ||
897 | } | ||
898 | "#, | ||
899 | expect![[r#" | ||
900 | 210..211 'f': impl Foo | ||
901 | 223..252 '{ ... &f; }': () | ||
902 | 233..234 '_': &dyn Foo | ||
903 | 247..249 '&f': &impl Foo | ||
904 | 248..249 'f': impl Foo | ||
905 | 247..249: expected &dyn Foo, got &impl Foo | ||
906 | "#]], | ||
859 | ); | 907 | ); |
860 | } | 908 | } |
861 | 909 | ||
@@ -912,3 +960,46 @@ fn test() -> i32 { | |||
912 | "#, | 960 | "#, |
913 | ) | 961 | ) |
914 | } | 962 | } |
963 | |||
964 | #[test] | ||
965 | fn panic_macro() { | ||
966 | check_infer_with_mismatches( | ||
967 | r#" | ||
968 | mod panic { | ||
969 | #[macro_export] | ||
970 | pub macro panic_2015 { | ||
971 | () => ( | ||
972 | $crate::panicking::panic() | ||
973 | ), | ||
974 | } | ||
975 | } | ||
976 | |||
977 | mod panicking { | ||
978 | pub fn panic() -> ! { loop {} } | ||
979 | } | ||
980 | |||
981 | #[rustc_builtin_macro = "core_panic"] | ||
982 | macro_rules! panic { | ||
983 | // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021` | ||
984 | // depending on the edition of the caller. | ||
985 | ($($arg:tt)*) => { | ||
986 | /* compiler built-in */ | ||
987 | }; | ||
988 | } | ||
989 | |||
990 | fn main() { | ||
991 | panic!() | ||
992 | } | ||
993 | "#, | ||
994 | expect![[r#" | ||
995 | 174..185 '{ loop {} }': ! | ||
996 | 176..183 'loop {}': ! | ||
997 | 181..183 '{}': () | ||
998 | !0..24 '$crate...:panic': fn panic() -> ! | ||
999 | !0..26 '$crate...anic()': ! | ||
1000 | !0..26 '$crate...anic()': ! | ||
1001 | !0..28 '$crate...015!()': ! | ||
1002 | 454..470 '{ ...c!() }': () | ||
1003 | "#]], | ||
1004 | ); | ||
1005 | } | ||
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 320694a17..ec3828ab2 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -286,7 +286,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | |||
286 | .and_then( | 286 | .and_then( |
287 | |url| if let Some(fragment) = fragment { url.join(&fragment).ok() } else { Some(url) }, | 287 | |url| if let Some(fragment) = fragment { url.join(&fragment).ok() } else { Some(url) }, |
288 | ) | 288 | ) |
289 | .map(|url| url.into_string()) | 289 | .map(|url| url.into()) |
290 | } | 290 | } |
291 | 291 | ||
292 | fn rewrite_intra_doc_link( | 292 | fn rewrite_intra_doc_link( |
@@ -325,7 +325,7 @@ fn rewrite_intra_doc_link( | |||
325 | }; | 325 | }; |
326 | } | 326 | } |
327 | 327 | ||
328 | Some((new_url.into_string(), strip_prefixes_suffixes(title).to_string())) | 328 | Some((new_url.into(), strip_prefixes_suffixes(title).to_string())) |
329 | } | 329 | } |
330 | 330 | ||
331 | /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). | 331 | /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). |
@@ -345,7 +345,7 @@ fn rewrite_url_link(db: &RootDatabase, def: ModuleDef, target: &str) -> Option<S | |||
345 | get_symbol_filename(db, &def).as_deref().map(|f| url.join(f).ok()).flatten() | 345 | get_symbol_filename(db, &def).as_deref().map(|f| url.join(f).ok()).flatten() |
346 | }) | 346 | }) |
347 | .and_then(|url| url.join(target).ok()) | 347 | .and_then(|url| url.join(target).ok()) |
348 | .map(|url| url.into_string()) | 348 | .map(|url| url.into()) |
349 | } | 349 | } |
350 | 350 | ||
351 | /// Rewrites a markdown document, applying 'callback' to each link. | 351 | /// Rewrites a markdown document, applying 'callback' to each link. |
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index f3284bb96..004d9cb68 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use ide_db::base_db::Upcast; | ||
1 | use ide_db::RootDatabase; | 2 | use ide_db::RootDatabase; |
2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 3 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
3 | 4 | ||
@@ -31,6 +32,7 @@ pub(crate) fn goto_type_definition( | |||
31 | ast::Pat(it) => sema.type_of_pat(&it)?, | 32 | ast::Pat(it) => sema.type_of_pat(&it)?, |
32 | ast::SelfParam(it) => sema.type_of_self(&it)?, | 33 | ast::SelfParam(it) => sema.type_of_self(&it)?, |
33 | ast::Type(it) => sema.resolve_type(&it)?, | 34 | ast::Type(it) => sema.resolve_type(&it)?, |
35 | ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?, | ||
34 | _ => return None, | 36 | _ => return None, |
35 | } | 37 | } |
36 | }; | 38 | }; |
@@ -161,4 +163,34 @@ impl Foo$0 {} | |||
161 | "#, | 163 | "#, |
162 | ) | 164 | ) |
163 | } | 165 | } |
166 | |||
167 | #[test] | ||
168 | fn goto_def_for_struct_field() { | ||
169 | check( | ||
170 | r#" | ||
171 | struct Bar; | ||
172 | //^^^ | ||
173 | |||
174 | struct Foo { | ||
175 | bar$0: Bar, | ||
176 | } | ||
177 | "#, | ||
178 | ); | ||
179 | } | ||
180 | |||
181 | #[test] | ||
182 | fn goto_def_for_enum_struct_field() { | ||
183 | check( | ||
184 | r#" | ||
185 | struct Bar; | ||
186 | //^^^ | ||
187 | |||
188 | enum Foo { | ||
189 | Bar { | ||
190 | bar$0: Bar | ||
191 | }, | ||
192 | } | ||
193 | "#, | ||
194 | ); | ||
195 | } | ||
164 | } | 196 | } |
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 8f490e922..85f887737 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -219,7 +219,7 @@ fn hint_iterator( | |||
219 | ) -> Option<SmolStr> { | 219 | ) -> Option<SmolStr> { |
220 | let db = sema.db; | 220 | let db = sema.db; |
221 | let strukt = ty.strip_references().as_adt()?; | 221 | let strukt = ty.strip_references().as_adt()?; |
222 | let krate = strukt.krate(db); | 222 | let krate = strukt.module(db).krate(); |
223 | if krate != famous_defs.core()? { | 223 | if krate != famous_defs.core()? { |
224 | return None; | 224 | return None; |
225 | } | 225 | } |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index f76715d84..ce1c76f37 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -227,7 +227,7 @@ pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> | |||
227 | let func = def.source(sema.db)?; | 227 | let func = def.source(sema.db)?; |
228 | let name_string = def.name(sema.db).to_string(); | 228 | let name_string = def.name(sema.db).to_string(); |
229 | 229 | ||
230 | let root = def.krate(sema.db)?.root_module(sema.db); | 230 | let root = def.module(sema.db).krate().root_module(sema.db); |
231 | 231 | ||
232 | let kind = if name_string == "main" && def.module(sema.db) == root { | 232 | let kind = if name_string == "main" && def.module(sema.db) == root { |
233 | RunnableKind::Bin | 233 | RunnableKind::Bin |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 9df8d21af..cf1a8bad7 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -80,6 +80,7 @@ pub(crate) fn highlight( | |||
80 | &mut hl, | 80 | &mut hl, |
81 | &sema, | 81 | &sema, |
82 | InFile::new(file_id.into(), &root), | 82 | InFile::new(file_id.into(), &root), |
83 | sema.scope(&root).krate(), | ||
83 | range_to_highlight, | 84 | range_to_highlight, |
84 | syntactic_name_ref_highlighting, | 85 | syntactic_name_ref_highlighting, |
85 | ); | 86 | ); |
@@ -90,6 +91,7 @@ fn traverse( | |||
90 | hl: &mut Highlights, | 91 | hl: &mut Highlights, |
91 | sema: &Semantics<RootDatabase>, | 92 | sema: &Semantics<RootDatabase>, |
92 | root: InFile<&SyntaxNode>, | 93 | root: InFile<&SyntaxNode>, |
94 | krate: Option<hir::Crate>, | ||
93 | range_to_highlight: TextRange, | 95 | range_to_highlight: TextRange, |
94 | syntactic_name_ref_highlighting: bool, | 96 | syntactic_name_ref_highlighting: bool, |
95 | ) { | 97 | ) { |
@@ -209,6 +211,7 @@ fn traverse( | |||
209 | 211 | ||
210 | if let Some((mut highlight, binding_hash)) = highlight::element( | 212 | if let Some((mut highlight, binding_hash)) = highlight::element( |
211 | &sema, | 213 | &sema, |
214 | krate, | ||
212 | &mut bindings_shadow_count, | 215 | &mut bindings_shadow_count, |
213 | syntactic_name_ref_highlighting, | 216 | syntactic_name_ref_highlighting, |
214 | element_to_highlight.clone(), | 217 | element_to_highlight.clone(), |
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 058e37ff0..b4a3d39c9 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | 19 | ||
20 | pub(super) fn element( | 20 | pub(super) fn element( |
21 | sema: &Semantics<RootDatabase>, | 21 | sema: &Semantics<RootDatabase>, |
22 | krate: Option<hir::Crate>, | ||
22 | bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, | 23 | bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, |
23 | syntactic_name_ref_highlighting: bool, | 24 | syntactic_name_ref_highlighting: bool, |
24 | element: SyntaxElement, | 25 | element: SyntaxElement, |
@@ -46,8 +47,10 @@ pub(super) fn element( | |||
46 | 47 | ||
47 | match name_kind { | 48 | match name_kind { |
48 | Some(NameClass::ExternCrate(_)) => SymbolKind::Module.into(), | 49 | Some(NameClass::ExternCrate(_)) => SymbolKind::Module.into(), |
49 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | 50 | Some(NameClass::Definition(def)) => { |
50 | Some(NameClass::ConstReference(def)) => highlight_def(db, def), | 51 | highlight_def(db, krate, def) | HlMod::Definition |
52 | } | ||
53 | Some(NameClass::ConstReference(def)) => highlight_def(db, krate, def), | ||
51 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { | 54 | Some(NameClass::PatFieldShorthand { field_ref, .. }) => { |
52 | let mut h = HlTag::Symbol(SymbolKind::Field).into(); | 55 | let mut h = HlTag::Symbol(SymbolKind::Field).into(); |
53 | if let Definition::Field(field) = field_ref { | 56 | if let Definition::Field(field) = field_ref { |
@@ -82,7 +85,7 @@ pub(super) fn element( | |||
82 | } | 85 | } |
83 | }; | 86 | }; |
84 | 87 | ||
85 | let mut h = highlight_def(db, def); | 88 | let mut h = highlight_def(db, krate, def); |
86 | 89 | ||
87 | if let Definition::Local(local) = &def { | 90 | if let Definition::Local(local) = &def { |
88 | if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) { | 91 | if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) { |
@@ -136,9 +139,11 @@ pub(super) fn element( | |||
136 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); | 139 | let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); |
137 | 140 | ||
138 | match NameClass::classify_lifetime(sema, &lifetime) { | 141 | match NameClass::classify_lifetime(sema, &lifetime) { |
139 | Some(NameClass::Definition(def)) => highlight_def(db, def) | HlMod::Definition, | 142 | Some(NameClass::Definition(def)) => { |
143 | highlight_def(db, krate, def) | HlMod::Definition | ||
144 | } | ||
140 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { | 145 | None => match NameRefClass::classify_lifetime(sema, &lifetime) { |
141 | Some(NameRefClass::Definition(def)) => highlight_def(db, def), | 146 | Some(NameRefClass::Definition(def)) => highlight_def(db, krate, def), |
142 | _ => SymbolKind::LifetimeParam.into(), | 147 | _ => SymbolKind::LifetimeParam.into(), |
143 | }, | 148 | }, |
144 | _ => Highlight::from(SymbolKind::LifetimeParam) | HlMod::Definition, | 149 | _ => Highlight::from(SymbolKind::LifetimeParam) | HlMod::Definition, |
@@ -277,12 +282,12 @@ pub(super) fn element( | |||
277 | hash((name, shadow_count)) | 282 | hash((name, shadow_count)) |
278 | } | 283 | } |
279 | } | 284 | } |
280 | fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | 285 | fn highlight_def(db: &RootDatabase, krate: Option<hir::Crate>, def: Definition) -> Highlight { |
281 | match def { | 286 | let mut h = match def { |
282 | Definition::Macro(_) => HlTag::Symbol(SymbolKind::Macro), | 287 | Definition::Macro(_) => Highlight::new(HlTag::Symbol(SymbolKind::Macro)), |
283 | Definition::Field(_) => HlTag::Symbol(SymbolKind::Field), | 288 | Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)), |
284 | Definition::ModuleDef(def) => match def { | 289 | Definition::ModuleDef(def) => match def { |
285 | hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module), | 290 | hir::ModuleDef::Module(_) => Highlight::new(HlTag::Symbol(SymbolKind::Module)), |
286 | hir::ModuleDef::Function(func) => { | 291 | hir::ModuleDef::Function(func) => { |
287 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); | 292 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); |
288 | if let Some(item) = func.as_assoc_item(db) { | 293 | if let Some(item) = func.as_assoc_item(db) { |
@@ -314,14 +319,22 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
314 | if func.is_async(db) { | 319 | if func.is_async(db) { |
315 | h |= HlMod::Async; | 320 | h |= HlMod::Async; |
316 | } | 321 | } |
317 | return h; | 322 | |
323 | h | ||
318 | } | 324 | } |
319 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HlTag::Symbol(SymbolKind::Struct), | 325 | hir::ModuleDef::Adt(adt) => { |
320 | hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HlTag::Symbol(SymbolKind::Enum), | 326 | let h = match adt { |
321 | hir::ModuleDef::Adt(hir::Adt::Union(_)) => HlTag::Symbol(SymbolKind::Union), | 327 | hir::Adt::Struct(_) => HlTag::Symbol(SymbolKind::Struct), |
322 | hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant), | 328 | hir::Adt::Enum(_) => HlTag::Symbol(SymbolKind::Enum), |
329 | hir::Adt::Union(_) => HlTag::Symbol(SymbolKind::Union), | ||
330 | }; | ||
331 | |||
332 | Highlight::new(h) | ||
333 | } | ||
334 | hir::ModuleDef::Variant(_) => Highlight::new(HlTag::Symbol(SymbolKind::Variant)), | ||
323 | hir::ModuleDef::Const(konst) => { | 335 | hir::ModuleDef::Const(konst) => { |
324 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); | 336 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); |
337 | |||
325 | if let Some(item) = konst.as_assoc_item(db) { | 338 | if let Some(item) = konst.as_assoc_item(db) { |
326 | h |= HlMod::Associated; | 339 | h |= HlMod::Associated; |
327 | match item.container(db) { | 340 | match item.container(db) { |
@@ -336,7 +349,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
336 | } | 349 | } |
337 | } | 350 | } |
338 | 351 | ||
339 | return h; | 352 | h |
340 | } | 353 | } |
341 | hir::ModuleDef::Trait(trait_) => { | 354 | hir::ModuleDef::Trait(trait_) => { |
342 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Trait)); | 355 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Trait)); |
@@ -344,10 +357,12 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
344 | if trait_.is_unsafe(db) { | 357 | if trait_.is_unsafe(db) { |
345 | h |= HlMod::Unsafe; | 358 | h |= HlMod::Unsafe; |
346 | } | 359 | } |
347 | return h; | 360 | |
361 | h | ||
348 | } | 362 | } |
349 | hir::ModuleDef::TypeAlias(type_) => { | 363 | hir::ModuleDef::TypeAlias(type_) => { |
350 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias)); | 364 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias)); |
365 | |||
351 | if let Some(item) = type_.as_assoc_item(db) { | 366 | if let Some(item) = type_.as_assoc_item(db) { |
352 | h |= HlMod::Associated; | 367 | h |= HlMod::Associated; |
353 | match item.container(db) { | 368 | match item.container(db) { |
@@ -361,23 +376,30 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
361 | } | 376 | } |
362 | } | 377 | } |
363 | } | 378 | } |
364 | return h; | 379 | |
380 | h | ||
365 | } | 381 | } |
366 | hir::ModuleDef::BuiltinType(_) => HlTag::BuiltinType, | 382 | hir::ModuleDef::BuiltinType(_) => Highlight::new(HlTag::BuiltinType), |
367 | hir::ModuleDef::Static(s) => { | 383 | hir::ModuleDef::Static(s) => { |
368 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Static)); | 384 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Static)); |
385 | |||
369 | if s.is_mut(db) { | 386 | if s.is_mut(db) { |
370 | h |= HlMod::Mutable; | 387 | h |= HlMod::Mutable; |
371 | h |= HlMod::Unsafe; | 388 | h |= HlMod::Unsafe; |
372 | } | 389 | } |
373 | return h; | 390 | |
391 | h | ||
374 | } | 392 | } |
375 | }, | 393 | }, |
376 | Definition::SelfType(_) => HlTag::Symbol(SymbolKind::Impl), | 394 | Definition::SelfType(_) => Highlight::new(HlTag::Symbol(SymbolKind::Impl)), |
377 | Definition::GenericParam(it) => match it { | 395 | Definition::GenericParam(it) => match it { |
378 | hir::GenericParam::TypeParam(_) => HlTag::Symbol(SymbolKind::TypeParam), | 396 | hir::GenericParam::TypeParam(_) => Highlight::new(HlTag::Symbol(SymbolKind::TypeParam)), |
379 | hir::GenericParam::ConstParam(_) => HlTag::Symbol(SymbolKind::ConstParam), | 397 | hir::GenericParam::ConstParam(_) => { |
380 | hir::GenericParam::LifetimeParam(_) => HlTag::Symbol(SymbolKind::LifetimeParam), | 398 | Highlight::new(HlTag::Symbol(SymbolKind::ConstParam)) |
399 | } | ||
400 | hir::GenericParam::LifetimeParam(_) => { | ||
401 | Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam)) | ||
402 | } | ||
381 | }, | 403 | }, |
382 | Definition::Local(local) => { | 404 | Definition::Local(local) => { |
383 | let tag = if local.is_self(db) { | 405 | let tag = if local.is_self(db) { |
@@ -395,11 +417,19 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
395 | if ty.as_callable(db).is_some() || ty.impls_fnonce(db) { | 417 | if ty.as_callable(db).is_some() || ty.impls_fnonce(db) { |
396 | h |= HlMod::Callable; | 418 | h |= HlMod::Callable; |
397 | } | 419 | } |
398 | return h; | 420 | h |
399 | } | 421 | } |
400 | Definition::Label(_) => HlTag::Symbol(SymbolKind::Label), | 422 | Definition::Label(_) => Highlight::new(HlTag::Symbol(SymbolKind::Label)), |
423 | }; | ||
424 | |||
425 | let is_from_other_crate = def.module(db).map(hir::Module::krate) != krate; | ||
426 | let is_builtin_type = matches!(def, Definition::ModuleDef(hir::ModuleDef::BuiltinType(_))); | ||
427 | |||
428 | if is_from_other_crate && !is_builtin_type { | ||
429 | h |= HlMod::Library; | ||
401 | } | 430 | } |
402 | .into() | 431 | |
432 | h | ||
403 | } | 433 | } |
404 | 434 | ||
405 | fn highlight_func_by_name_ref( | 435 | fn highlight_func_by_name_ref( |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 27473a2f9..e94f17cd9 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -67,6 +67,8 @@ pub enum HlMod { | |||
67 | Trait, | 67 | Trait, |
68 | /// Used with keywords like `async` and `await`. | 68 | /// Used with keywords like `async` and `await`. |
69 | Async, | 69 | Async, |
70 | /// Used for items from other crates. | ||
71 | Library, | ||
70 | // Keep this last! | 72 | // Keep this last! |
71 | /// Used for unsafe functions, unsafe traits, mutable statics, union accesses and unsafe operations. | 73 | /// Used for unsafe functions, unsafe traits, mutable statics, union accesses and unsafe operations. |
72 | Unsafe, | 74 | Unsafe, |
@@ -189,6 +191,7 @@ impl HlMod { | |||
189 | HlMod::Static, | 191 | HlMod::Static, |
190 | HlMod::Trait, | 192 | HlMod::Trait, |
191 | HlMod::Async, | 193 | HlMod::Async, |
194 | HlMod::Library, | ||
192 | HlMod::Unsafe, | 195 | HlMod::Unsafe, |
193 | ]; | 196 | ]; |
194 | 197 | ||
@@ -207,6 +210,7 @@ impl HlMod { | |||
207 | HlMod::Static => "static", | 210 | HlMod::Static => "static", |
208 | HlMod::Trait => "trait", | 211 | HlMod::Trait => "trait", |
209 | HlMod::Async => "async", | 212 | HlMod::Async => "async", |
213 | HlMod::Library => "library", | ||
210 | HlMod::Unsafe => "unsafe", | 214 | HlMod::Unsafe => "unsafe", |
211 | } | 215 | } |
212 | } | 216 | } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 878431b56..055d21109 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -248,4 +248,20 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
248 | <span class="brace">}</span> | 248 | <span class="brace">}</span> |
249 | 249 | ||
250 | <span class="keyword unsafe">unsafe</span> <span class="keyword">trait</span> <span class="trait declaration unsafe">Dangerous</span> <span class="brace">{</span><span class="brace">}</span> | 250 | <span class="keyword unsafe">unsafe</span> <span class="keyword">trait</span> <span class="trait declaration unsafe">Dangerous</span> <span class="brace">{</span><span class="brace">}</span> |
251 | <span class="keyword">impl</span> <span class="trait unsafe">Dangerous</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre> \ No newline at end of file | 251 | <span class="keyword">impl</span> <span class="trait unsafe">Dangerous</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
252 | |||
253 | <span class="keyword">fn</span> <span class="function declaration">use_foo_items</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | ||
254 | <span class="keyword">let</span> <span class="variable declaration">bob</span> <span class="operator">=</span> <span class="module library">foo</span><span class="operator">::</span><span class="struct library">Person</span> <span class="brace">{</span> | ||
255 | <span class="field library">name</span><span class="colon">:</span> <span class="string_literal">"Bob"</span><span class="comma">,</span> | ||
256 | <span class="field library">age</span><span class="colon">:</span> <span class="module library">foo</span><span class="operator">::</span><span class="module library">consts</span><span class="operator">::</span><span class="constant library">NUMBER</span><span class="comma">,</span> | ||
257 | <span class="brace">}</span><span class="semicolon">;</span> | ||
258 | |||
259 | <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span> | ||
260 | |||
261 | <span class="keyword control">if</span> <span class="keyword">let</span> <span class="module library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Die</span> <span class="operator">=</span> <span class="variable">control_flow</span> <span class="brace">{</span> | ||
262 | foo::<span class="macro">die!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | ||
263 | <span class="brace">}</span> | ||
264 | <span class="brace">}</span> | ||
265 | |||
266 | |||
267 | </code></pre> \ No newline at end of file | ||
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 9ce26e930..be4447ebb 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -10,6 +10,7 @@ use crate::{fixture, FileRange, HlTag, TextRange}; | |||
10 | fn test_highlighting() { | 10 | fn test_highlighting() { |
11 | check_highlighting( | 11 | check_highlighting( |
12 | r#" | 12 | r#" |
13 | //- /main.rs crate:main deps:foo | ||
13 | use inner::{self as inner_mod}; | 14 | use inner::{self as inner_mod}; |
14 | mod inner {} | 15 | mod inner {} |
15 | 16 | ||
@@ -222,6 +223,43 @@ async fn async_main() { | |||
222 | 223 | ||
223 | unsafe trait Dangerous {} | 224 | unsafe trait Dangerous {} |
224 | impl Dangerous for () {} | 225 | impl Dangerous for () {} |
226 | |||
227 | fn use_foo_items() { | ||
228 | let bob = foo::Person { | ||
229 | name: "Bob", | ||
230 | age: foo::consts::NUMBER, | ||
231 | }; | ||
232 | |||
233 | let control_flow = foo::identity(foo::ControlFlow::Continue); | ||
234 | |||
235 | if let foo::ControlFlow::Die = control_flow { | ||
236 | foo::die!(); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | |||
241 | //- /foo.rs crate:foo | ||
242 | pub struct Person { | ||
243 | pub name: &'static str, | ||
244 | pub age: u8, | ||
245 | } | ||
246 | |||
247 | pub enum ControlFlow { | ||
248 | Continue, | ||
249 | Die, | ||
250 | } | ||
251 | |||
252 | pub fn identity<T>(x: T) -> T { x } | ||
253 | |||
254 | pub mod consts { | ||
255 | pub const NUMBER: i64 = 92; | ||
256 | } | ||
257 | |||
258 | macro_rules! die { | ||
259 | () => { | ||
260 | panic!(); | ||
261 | }; | ||
262 | } | ||
225 | "# | 263 | "# |
226 | .trim(), | 264 | .trim(), |
227 | expect_file!["./test_data/highlighting.html"], | 265 | expect_file!["./test_data/highlighting.html"], |
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs index 97435f021..3d2cd739a 100644 --- a/crates/ide_assists/src/handlers/fill_match_arms.rs +++ b/crates/ide_assists/src/handlers/fill_match_arms.rs | |||
@@ -31,8 +31,8 @@ use crate::{ | |||
31 | // | 31 | // |
32 | // fn handle(action: Action) { | 32 | // fn handle(action: Action) { |
33 | // match action { | 33 | // match action { |
34 | // $0Action::Move { distance } => {} | 34 | // $0Action::Move { distance } => todo!(), |
35 | // Action::Stop => {} | 35 | // Action::Stop => todo!(), |
36 | // } | 36 | // } |
37 | // } | 37 | // } |
38 | // ``` | 38 | // ``` |
@@ -129,7 +129,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
129 | |builder| { | 129 | |builder| { |
130 | let new_match_arm_list = match_arm_list.clone_for_update(); | 130 | let new_match_arm_list = match_arm_list.clone_for_update(); |
131 | let missing_arms = missing_pats | 131 | let missing_arms = missing_pats |
132 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) | 132 | .map(|pat| make::match_arm(iter::once(pat), make::ext::expr_todo())) |
133 | .map(|it| it.clone_for_update()); | 133 | .map(|it| it.clone_for_update()); |
134 | 134 | ||
135 | let catch_all_arm = new_match_arm_list | 135 | let catch_all_arm = new_match_arm_list |
@@ -350,8 +350,8 @@ fn foo(a: bool) { | |||
350 | r#" | 350 | r#" |
351 | fn foo(a: bool) { | 351 | fn foo(a: bool) { |
352 | match a { | 352 | match a { |
353 | $0true => {} | 353 | $0true => todo!(), |
354 | false => {} | 354 | false => todo!(), |
355 | } | 355 | } |
356 | } | 356 | } |
357 | "#, | 357 | "#, |
@@ -373,7 +373,7 @@ fn foo(a: bool) { | |||
373 | fn foo(a: bool) { | 373 | fn foo(a: bool) { |
374 | match a { | 374 | match a { |
375 | true => {} | 375 | true => {} |
376 | $0false => {} | 376 | $0false => todo!(), |
377 | } | 377 | } |
378 | } | 378 | } |
379 | "#, | 379 | "#, |
@@ -410,10 +410,10 @@ fn foo(a: bool) { | |||
410 | r#" | 410 | r#" |
411 | fn foo(a: bool) { | 411 | fn foo(a: bool) { |
412 | match (a, a) { | 412 | match (a, a) { |
413 | $0(true, true) => {} | 413 | $0(true, true) => todo!(), |
414 | (true, false) => {} | 414 | (true, false) => todo!(), |
415 | (false, true) => {} | 415 | (false, true) => todo!(), |
416 | (false, false) => {} | 416 | (false, false) => todo!(), |
417 | } | 417 | } |
418 | } | 418 | } |
419 | "#, | 419 | "#, |
@@ -435,9 +435,9 @@ fn foo(a: bool) { | |||
435 | fn foo(a: bool) { | 435 | fn foo(a: bool) { |
436 | match (a, a) { | 436 | match (a, a) { |
437 | (false, true) => {} | 437 | (false, true) => {} |
438 | $0(true, true) => {} | 438 | $0(true, true) => todo!(), |
439 | (true, false) => {} | 439 | (true, false) => todo!(), |
440 | (false, false) => {} | 440 | (false, false) => todo!(), |
441 | } | 441 | } |
442 | } | 442 | } |
443 | "#, | 443 | "#, |
@@ -471,7 +471,7 @@ fn main() { | |||
471 | match A::As { | 471 | match A::As { |
472 | A::Bs { x, y: Some(_) } => {} | 472 | A::Bs { x, y: Some(_) } => {} |
473 | A::Cs(_, Some(_)) => {} | 473 | A::Cs(_, Some(_)) => {} |
474 | $0A::As => {} | 474 | $0A::As => todo!(), |
475 | } | 475 | } |
476 | } | 476 | } |
477 | "#, | 477 | "#, |
@@ -499,7 +499,7 @@ use Option::*; | |||
499 | fn main() { | 499 | fn main() { |
500 | match None { | 500 | match None { |
501 | None => {} | 501 | None => {} |
502 | Some(${0:_}) => {} | 502 | Some(${0:_}) => todo!(), |
503 | } | 503 | } |
504 | } | 504 | } |
505 | "#, | 505 | "#, |
@@ -523,7 +523,7 @@ enum A { As, Bs, Cs(Option<i32>) } | |||
523 | fn main() { | 523 | fn main() { |
524 | match A::As { | 524 | match A::As { |
525 | A::Cs(_) | A::Bs => {} | 525 | A::Cs(_) | A::Bs => {} |
526 | $0A::As => {} | 526 | $0A::As => todo!(), |
527 | } | 527 | } |
528 | } | 528 | } |
529 | "#, | 529 | "#, |
@@ -553,8 +553,8 @@ fn main() { | |||
553 | A::Bs if 0 < 1 => {} | 553 | A::Bs if 0 < 1 => {} |
554 | A::Ds(_value) => { let x = 1; } | 554 | A::Ds(_value) => { let x = 1; } |
555 | A::Es(B::Xs) => (), | 555 | A::Es(B::Xs) => (), |
556 | $0A::As => {} | 556 | $0A::As => todo!(), |
557 | A::Cs => {} | 557 | A::Cs => todo!(), |
558 | } | 558 | } |
559 | } | 559 | } |
560 | "#, | 560 | "#, |
@@ -580,7 +580,7 @@ fn main() { | |||
580 | match A::As { | 580 | match A::As { |
581 | A::As(_) => {} | 581 | A::As(_) => {} |
582 | a @ A::Bs(_) => {} | 582 | a @ A::Bs(_) => {} |
583 | A::Cs(${0:_}) => {} | 583 | A::Cs(${0:_}) => todo!(), |
584 | } | 584 | } |
585 | } | 585 | } |
586 | "#, | 586 | "#, |
@@ -605,11 +605,11 @@ enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } } | |||
605 | fn main() { | 605 | fn main() { |
606 | let a = A::As; | 606 | let a = A::As; |
607 | match a { | 607 | match a { |
608 | $0A::As => {} | 608 | $0A::As => todo!(), |
609 | A::Bs => {} | 609 | A::Bs => todo!(), |
610 | A::Cs(_) => {} | 610 | A::Cs(_) => todo!(), |
611 | A::Ds(_, _) => {} | 611 | A::Ds(_, _) => todo!(), |
612 | A::Es { x, y } => {} | 612 | A::Es { x, y } => todo!(), |
613 | } | 613 | } |
614 | } | 614 | } |
615 | "#, | 615 | "#, |
@@ -638,10 +638,10 @@ fn main() { | |||
638 | let a = A::One; | 638 | let a = A::One; |
639 | let b = B::One; | 639 | let b = B::One; |
640 | match (a, b) { | 640 | match (a, b) { |
641 | $0(A::One, B::One) => {} | 641 | $0(A::One, B::One) => todo!(), |
642 | (A::One, B::Two) => {} | 642 | (A::One, B::Two) => todo!(), |
643 | (A::Two, B::One) => {} | 643 | (A::Two, B::One) => todo!(), |
644 | (A::Two, B::Two) => {} | 644 | (A::Two, B::Two) => todo!(), |
645 | } | 645 | } |
646 | } | 646 | } |
647 | "#, | 647 | "#, |
@@ -670,10 +670,10 @@ fn main() { | |||
670 | let a = A::One; | 670 | let a = A::One; |
671 | let b = B::One; | 671 | let b = B::One; |
672 | match (&a, &b) { | 672 | match (&a, &b) { |
673 | $0(A::One, B::One) => {} | 673 | $0(A::One, B::One) => todo!(), |
674 | (A::One, B::Two) => {} | 674 | (A::One, B::Two) => todo!(), |
675 | (A::Two, B::One) => {} | 675 | (A::Two, B::One) => todo!(), |
676 | (A::Two, B::Two) => {} | 676 | (A::Two, B::Two) => todo!(), |
677 | } | 677 | } |
678 | } | 678 | } |
679 | "#, | 679 | "#, |
@@ -705,9 +705,9 @@ fn main() { | |||
705 | let b = B::One; | 705 | let b = B::One; |
706 | match (a, b) { | 706 | match (a, b) { |
707 | (A::Two, B::One) => {} | 707 | (A::Two, B::One) => {} |
708 | $0(A::One, B::One) => {} | 708 | $0(A::One, B::One) => todo!(), |
709 | (A::One, B::Two) => {} | 709 | (A::One, B::Two) => todo!(), |
710 | (A::Two, B::Two) => {} | 710 | (A::Two, B::Two) => todo!(), |
711 | } | 711 | } |
712 | } | 712 | } |
713 | "#, | 713 | "#, |
@@ -736,7 +736,7 @@ fn main() { | |||
736 | match (a, b) { | 736 | match (a, b) { |
737 | (Some(_), _) => {} | 737 | (Some(_), _) => {} |
738 | (None, Some(_)) => {} | 738 | (None, Some(_)) => {} |
739 | $0(None, None) => {} | 739 | $0(None, None) => todo!(), |
740 | } | 740 | } |
741 | } | 741 | } |
742 | "#, | 742 | "#, |
@@ -801,8 +801,8 @@ enum A { One, Two } | |||
801 | fn main() { | 801 | fn main() { |
802 | let a = A::One; | 802 | let a = A::One; |
803 | match (a, ) { | 803 | match (a, ) { |
804 | $0(A::One,) => {} | 804 | $0(A::One,) => todo!(), |
805 | (A::Two,) => {} | 805 | (A::Two,) => todo!(), |
806 | } | 806 | } |
807 | } | 807 | } |
808 | "#, | 808 | "#, |
@@ -826,7 +826,7 @@ enum A { As } | |||
826 | 826 | ||
827 | fn foo(a: &A) { | 827 | fn foo(a: &A) { |
828 | match a { | 828 | match a { |
829 | $0A::As => {} | 829 | $0A::As => todo!(), |
830 | } | 830 | } |
831 | } | 831 | } |
832 | "#, | 832 | "#, |
@@ -851,7 +851,7 @@ enum A { | |||
851 | 851 | ||
852 | fn foo(a: &mut A) { | 852 | fn foo(a: &mut A) { |
853 | match a { | 853 | match a { |
854 | $0A::Es { x, y } => {} | 854 | $0A::Es { x, y } => todo!(), |
855 | } | 855 | } |
856 | } | 856 | } |
857 | "#, | 857 | "#, |
@@ -891,8 +891,8 @@ enum E { X, Y } | |||
891 | 891 | ||
892 | fn main() { | 892 | fn main() { |
893 | match E::X { | 893 | match E::X { |
894 | $0E::X => {} | 894 | $0E::X => todo!(), |
895 | E::Y => {} | 895 | E::Y => todo!(), |
896 | } | 896 | } |
897 | } | 897 | } |
898 | "#, | 898 | "#, |
@@ -919,8 +919,8 @@ use foo::E::X; | |||
919 | 919 | ||
920 | fn main() { | 920 | fn main() { |
921 | match X { | 921 | match X { |
922 | $0X => {} | 922 | $0X => todo!(), |
923 | foo::E::Y => {} | 923 | foo::E::Y => todo!(), |
924 | } | 924 | } |
925 | } | 925 | } |
926 | "#, | 926 | "#, |
@@ -947,7 +947,7 @@ fn foo(a: A) { | |||
947 | match a { | 947 | match a { |
948 | // foo bar baz | 948 | // foo bar baz |
949 | A::One => {} | 949 | A::One => {} |
950 | $0A::Two => {} | 950 | $0A::Two => todo!(), |
951 | // This is where the rest should be | 951 | // This is where the rest should be |
952 | } | 952 | } |
953 | } | 953 | } |
@@ -971,8 +971,8 @@ fn foo(a: A) { | |||
971 | enum A { One, Two } | 971 | enum A { One, Two } |
972 | fn foo(a: A) { | 972 | fn foo(a: A) { |
973 | match a { | 973 | match a { |
974 | $0A::One => {} | 974 | $0A::One => todo!(), |
975 | A::Two => {} | 975 | A::Two => todo!(), |
976 | // foo bar baz | 976 | // foo bar baz |
977 | } | 977 | } |
978 | } | 978 | } |
@@ -996,8 +996,8 @@ fn foo(a: A) { | |||
996 | enum A { One, Two, } | 996 | enum A { One, Two, } |
997 | fn foo(a: A) { | 997 | fn foo(a: A) { |
998 | match a { | 998 | match a { |
999 | $0A::One => {} | 999 | $0A::One => todo!(), |
1000 | A::Two => {} | 1000 | A::Two => todo!(), |
1001 | } | 1001 | } |
1002 | } | 1002 | } |
1003 | "#, | 1003 | "#, |
@@ -1021,8 +1021,8 @@ fn foo(opt: Option<i32>) { | |||
1021 | r#" | 1021 | r#" |
1022 | fn foo(opt: Option<i32>) { | 1022 | fn foo(opt: Option<i32>) { |
1023 | match opt { | 1023 | match opt { |
1024 | Some(${0:_}) => {} | 1024 | Some(${0:_}) => todo!(), |
1025 | None => {} | 1025 | None => todo!(), |
1026 | } | 1026 | } |
1027 | } | 1027 | } |
1028 | "#, | 1028 | "#, |
@@ -1054,9 +1054,9 @@ enum Test { | |||
1054 | 1054 | ||
1055 | fn foo(t: Test) { | 1055 | fn foo(t: Test) { |
1056 | m!(match t { | 1056 | m!(match t { |
1057 | $0Test::A => {} | 1057 | $0Test::A => todo!(), |
1058 | Test::B => {} | 1058 | Test::B => todo!(), |
1059 | Test::C => {} | 1059 | Test::C => todo!(), |
1060 | }); | 1060 | }); |
1061 | }"#, | 1061 | }"#, |
1062 | ); | 1062 | ); |
@@ -1076,4 +1076,44 @@ fn foo(tuple: (A, A)) { | |||
1076 | "#, | 1076 | "#, |
1077 | ); | 1077 | ); |
1078 | } | 1078 | } |
1079 | |||
1080 | #[test] | ||
1081 | fn adds_comma_before_new_arms() { | ||
1082 | check_assist( | ||
1083 | fill_match_arms, | ||
1084 | r#" | ||
1085 | fn foo(t: bool) { | ||
1086 | match $0t { | ||
1087 | true => 1 + 2 | ||
1088 | } | ||
1089 | }"#, | ||
1090 | r#" | ||
1091 | fn foo(t: bool) { | ||
1092 | match t { | ||
1093 | true => 1 + 2, | ||
1094 | $0false => todo!(), | ||
1095 | } | ||
1096 | }"#, | ||
1097 | ); | ||
1098 | } | ||
1099 | |||
1100 | #[test] | ||
1101 | fn does_not_add_extra_comma() { | ||
1102 | check_assist( | ||
1103 | fill_match_arms, | ||
1104 | r#" | ||
1105 | fn foo(t: bool) { | ||
1106 | match $0t { | ||
1107 | true => 1 + 2, | ||
1108 | } | ||
1109 | }"#, | ||
1110 | r#" | ||
1111 | fn foo(t: bool) { | ||
1112 | match t { | ||
1113 | true => 1 + 2, | ||
1114 | $0false => todo!(), | ||
1115 | } | ||
1116 | }"#, | ||
1117 | ); | ||
1118 | } | ||
1079 | } | 1119 | } |
diff --git a/crates/ide_assists/src/handlers/fix_visibility.rs b/crates/ide_assists/src/handlers/fix_visibility.rs index 6c7824e55..89f7b2c2c 100644 --- a/crates/ide_assists/src/handlers/fix_visibility.rs +++ b/crates/ide_assists/src/handlers/fix_visibility.rs | |||
@@ -85,7 +85,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
85 | 85 | ||
86 | fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 86 | fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
87 | let record_field: ast::RecordExprField = ctx.find_node_at_offset()?; | 87 | let record_field: ast::RecordExprField = ctx.find_node_at_offset()?; |
88 | let (record_field_def, _) = ctx.sema.resolve_record_field(&record_field)?; | 88 | let (record_field_def, _, _) = ctx.sema.resolve_record_field(&record_field)?; |
89 | 89 | ||
90 | let current_module = ctx.sema.scope(record_field.syntax()).module()?; | 90 | let current_module = ctx.sema.scope(record_field.syntax()).module()?; |
91 | let visibility = record_field_def.visibility(ctx.db()); | 91 | let visibility = record_field_def.visibility(ctx.db()); |
diff --git a/crates/ide_assists/src/handlers/generate_getter.rs b/crates/ide_assists/src/handlers/generate_getter.rs index df7d1bb95..09971226e 100644 --- a/crates/ide_assists/src/handlers/generate_getter.rs +++ b/crates/ide_assists/src/handlers/generate_getter.rs | |||
@@ -23,12 +23,46 @@ use crate::{ | |||
23 | // | 23 | // |
24 | // impl Person { | 24 | // impl Person { |
25 | // /// Get a reference to the person's name. | 25 | // /// Get a reference to the person's name. |
26 | // fn name(&self) -> &String { | 26 | // fn $0name(&self) -> &str { |
27 | // &self.name | 27 | // self.name.as_str() |
28 | // } | 28 | // } |
29 | // } | 29 | // } |
30 | // ``` | 30 | // ``` |
31 | pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 31 | pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
32 | generate_getter_impl(acc, ctx, false) | ||
33 | } | ||
34 | |||
35 | // Assist: generate_getter_mut | ||
36 | // | ||
37 | // Generate a mut getter method. | ||
38 | // | ||
39 | // ``` | ||
40 | // struct Person { | ||
41 | // nam$0e: String, | ||
42 | // } | ||
43 | // ``` | ||
44 | // -> | ||
45 | // ``` | ||
46 | // struct Person { | ||
47 | // name: String, | ||
48 | // } | ||
49 | // | ||
50 | // impl Person { | ||
51 | // /// Get a mutable reference to the person's name. | ||
52 | // fn $0name_mut(&mut self) -> &mut String { | ||
53 | // &mut self.name | ||
54 | // } | ||
55 | // } | ||
56 | // ``` | ||
57 | pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
58 | generate_getter_impl(acc, ctx, true) | ||
59 | } | ||
60 | |||
61 | pub(crate) fn generate_getter_impl( | ||
62 | acc: &mut Assists, | ||
63 | ctx: &AssistContext, | ||
64 | mutable: bool, | ||
65 | ) -> Option<()> { | ||
32 | let strukt = ctx.find_node_at_offset::<ast::Struct>()?; | 66 | let strukt = ctx.find_node_at_offset::<ast::Struct>()?; |
33 | let field = ctx.find_node_at_offset::<ast::RecordField>()?; | 67 | let field = ctx.find_node_at_offset::<ast::RecordField>()?; |
34 | 68 | ||
@@ -37,39 +71,52 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
37 | let field_ty = field.ty()?; | 71 | let field_ty = field.ty()?; |
38 | 72 | ||
39 | // Return early if we've found an existing fn | 73 | // Return early if we've found an existing fn |
40 | let fn_name = to_lower_snake_case(&field_name.to_string()); | 74 | let mut fn_name = to_lower_snake_case(&field_name.to_string()); |
75 | if mutable { | ||
76 | format_to!(fn_name, "_mut"); | ||
77 | } | ||
41 | let impl_def = find_struct_impl(&ctx, &ast::Adt::Struct(strukt.clone()), fn_name.as_str())?; | 78 | let impl_def = find_struct_impl(&ctx, &ast::Adt::Struct(strukt.clone()), fn_name.as_str())?; |
42 | 79 | ||
80 | let (id, label) = if mutable { | ||
81 | ("generate_getter_mut", "Generate a mut getter method") | ||
82 | } else { | ||
83 | ("generate_getter", "Generate a getter method") | ||
84 | }; | ||
43 | let target = field.syntax().text_range(); | 85 | let target = field.syntax().text_range(); |
44 | acc.add_group( | 86 | acc.add_group( |
45 | &GroupLabel("Generate getter/setter".to_owned()), | 87 | &GroupLabel("Generate getter/setter".to_owned()), |
46 | AssistId("generate_getter", AssistKind::Generate), | 88 | AssistId(id, AssistKind::Generate), |
47 | "Generate a getter method", | 89 | label, |
48 | target, | 90 | target, |
49 | |builder| { | 91 | |builder| { |
50 | let mut buf = String::with_capacity(512); | 92 | let mut buf = String::with_capacity(512); |
51 | 93 | ||
52 | let fn_name_spaced = fn_name.replace('_', " "); | ||
53 | let strukt_name_spaced = | ||
54 | to_lower_snake_case(&strukt_name.to_string()).replace('_', " "); | ||
55 | |||
56 | if impl_def.is_some() { | 94 | if impl_def.is_some() { |
57 | buf.push('\n'); | 95 | buf.push('\n'); |
58 | } | 96 | } |
59 | 97 | ||
60 | let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); | 98 | let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v)); |
99 | let (ty, body) = if mutable { | ||
100 | (format!("&mut {}", field_ty), format!("&mut self.{}", field_name)) | ||
101 | } else { | ||
102 | useless_type_special_case(&field_name.to_string(), &field_ty) | ||
103 | .unwrap_or_else(|| (format!("&{}", field_ty), format!("&self.{}", field_name))) | ||
104 | }; | ||
105 | |||
61 | format_to!( | 106 | format_to!( |
62 | buf, | 107 | buf, |
63 | " /// Get a reference to the {}'s {}. | 108 | " /// Get a {}reference to the {}'s {}. |
64 | {}fn {}(&self) -> &{} {{ | 109 | {}fn {}(&{}self) -> {} {{ |
65 | &self.{} | 110 | {} |
66 | }}", | 111 | }}", |
67 | strukt_name_spaced, | 112 | mutable.then(|| "mutable ").unwrap_or_default(), |
68 | fn_name_spaced, | 113 | to_lower_snake_case(&strukt_name.to_string()).replace('_', " "), |
114 | fn_name.trim_end_matches("_mut").replace('_', " "), | ||
69 | vis, | 115 | vis, |
70 | fn_name, | 116 | fn_name, |
71 | field_ty, | 117 | mutable.then(|| "mut ").unwrap_or_default(), |
72 | fn_name, | 118 | ty, |
119 | body, | ||
73 | ); | 120 | ); |
74 | 121 | ||
75 | let start_offset = impl_def | 122 | let start_offset = impl_def |
@@ -79,56 +126,120 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
79 | strukt.syntax().text_range().end() | 126 | strukt.syntax().text_range().end() |
80 | }); | 127 | }); |
81 | 128 | ||
82 | builder.insert(start_offset, buf); | 129 | match ctx.config.snippet_cap { |
130 | Some(cap) => { | ||
131 | builder.insert_snippet(cap, start_offset, buf.replacen("fn ", "fn $0", 1)) | ||
132 | } | ||
133 | None => builder.insert(start_offset, buf), | ||
134 | } | ||
83 | }, | 135 | }, |
84 | ) | 136 | ) |
85 | } | 137 | } |
86 | 138 | ||
139 | fn useless_type_special_case(field_name: &str, field_ty: &ast::Type) -> Option<(String, String)> { | ||
140 | if field_ty.to_string() == "String" { | ||
141 | cov_mark::hit!(useless_type_special_case); | ||
142 | return Some(("&str".to_string(), format!("self.{}.as_str()", field_name))); | ||
143 | } | ||
144 | if let Some(arg) = ty_ctor(field_ty, "Vec") { | ||
145 | return Some((format!("&[{}]", arg), format!("self.{}.as_slice()", field_name))); | ||
146 | } | ||
147 | if let Some(arg) = ty_ctor(field_ty, "Box") { | ||
148 | return Some((format!("&{}", arg), format!("self.{}.as_ref()", field_name))); | ||
149 | } | ||
150 | if let Some(arg) = ty_ctor(field_ty, "Option") { | ||
151 | return Some((format!("Option<&{}>", arg), format!("self.{}.as_ref()", field_name))); | ||
152 | } | ||
153 | None | ||
154 | } | ||
155 | |||
156 | // FIXME: This should rely on semantic info. | ||
157 | fn ty_ctor(ty: &ast::Type, ctor: &str) -> Option<String> { | ||
158 | let res = ty.to_string().strip_prefix(ctor)?.strip_prefix('<')?.strip_suffix('>')?.to_string(); | ||
159 | Some(res) | ||
160 | } | ||
161 | |||
87 | #[cfg(test)] | 162 | #[cfg(test)] |
88 | mod tests { | 163 | mod tests { |
89 | use crate::tests::{check_assist, check_assist_not_applicable}; | 164 | use crate::tests::{check_assist, check_assist_not_applicable}; |
90 | 165 | ||
91 | use super::*; | 166 | use super::*; |
92 | 167 | ||
93 | fn check_not_applicable(ra_fixture: &str) { | ||
94 | check_assist_not_applicable(generate_getter, ra_fixture) | ||
95 | } | ||
96 | |||
97 | #[test] | 168 | #[test] |
98 | fn test_generate_getter_from_field() { | 169 | fn test_generate_getter_from_field() { |
99 | check_assist( | 170 | check_assist( |
100 | generate_getter, | 171 | generate_getter, |
101 | r#" | 172 | r#" |
102 | struct Context<T: Clone> { | 173 | struct Context { |
103 | dat$0a: T, | 174 | dat$0a: Data, |
104 | }"#, | 175 | } |
176 | "#, | ||
105 | r#" | 177 | r#" |
106 | struct Context<T: Clone> { | 178 | struct Context { |
107 | data: T, | 179 | data: Data, |
108 | } | 180 | } |
109 | 181 | ||
110 | impl<T: Clone> Context<T> { | 182 | impl Context { |
111 | /// Get a reference to the context's data. | 183 | /// Get a reference to the context's data. |
112 | fn data(&self) -> &T { | 184 | fn $0data(&self) -> &Data { |
113 | &self.data | 185 | &self.data |
114 | } | 186 | } |
115 | }"#, | 187 | } |
188 | "#, | ||
189 | ); | ||
190 | |||
191 | check_assist( | ||
192 | generate_getter_mut, | ||
193 | r#" | ||
194 | struct Context { | ||
195 | dat$0a: Data, | ||
196 | } | ||
197 | "#, | ||
198 | r#" | ||
199 | struct Context { | ||
200 | data: Data, | ||
201 | } | ||
202 | |||
203 | impl Context { | ||
204 | /// Get a mutable reference to the context's data. | ||
205 | fn $0data_mut(&mut self) -> &mut Data { | ||
206 | &mut self.data | ||
207 | } | ||
208 | } | ||
209 | "#, | ||
116 | ); | 210 | ); |
117 | } | 211 | } |
118 | 212 | ||
119 | #[test] | 213 | #[test] |
120 | fn test_generate_getter_already_implemented() { | 214 | fn test_generate_getter_already_implemented() { |
121 | check_not_applicable( | 215 | check_assist_not_applicable( |
216 | generate_getter, | ||
122 | r#" | 217 | r#" |
123 | struct Context<T: Clone> { | 218 | struct Context { |
124 | dat$0a: T, | 219 | dat$0a: Data, |
125 | } | 220 | } |
126 | 221 | ||
127 | impl<T: Clone> Context<T> { | 222 | impl Context { |
128 | fn data(&self) -> &T { | 223 | fn data(&self) -> &Data { |
129 | &self.data | 224 | &self.data |
130 | } | 225 | } |
131 | }"#, | 226 | } |
227 | "#, | ||
228 | ); | ||
229 | |||
230 | check_assist_not_applicable( | ||
231 | generate_getter_mut, | ||
232 | r#" | ||
233 | struct Context { | ||
234 | dat$0a: Data, | ||
235 | } | ||
236 | |||
237 | impl Context { | ||
238 | fn data_mut(&mut self) -> &mut Data { | ||
239 | &mut self.data | ||
240 | } | ||
241 | } | ||
242 | "#, | ||
132 | ); | 243 | ); |
133 | } | 244 | } |
134 | 245 | ||
@@ -137,20 +248,22 @@ impl<T: Clone> Context<T> { | |||
137 | check_assist( | 248 | check_assist( |
138 | generate_getter, | 249 | generate_getter, |
139 | r#" | 250 | r#" |
140 | pub(crate) struct Context<T: Clone> { | 251 | pub(crate) struct Context { |
141 | dat$0a: T, | 252 | dat$0a: Data, |
142 | }"#, | 253 | } |
254 | "#, | ||
143 | r#" | 255 | r#" |
144 | pub(crate) struct Context<T: Clone> { | 256 | pub(crate) struct Context { |
145 | data: T, | 257 | data: Data, |
146 | } | 258 | } |
147 | 259 | ||
148 | impl<T: Clone> Context<T> { | 260 | impl Context { |
149 | /// Get a reference to the context's data. | 261 | /// Get a reference to the context's data. |
150 | pub(crate) fn data(&self) -> &T { | 262 | pub(crate) fn $0data(&self) -> &Data { |
151 | &self.data | 263 | &self.data |
152 | } | 264 | } |
153 | }"#, | 265 | } |
266 | "#, | ||
154 | ); | 267 | ); |
155 | } | 268 | } |
156 | 269 | ||
@@ -159,34 +272,105 @@ impl<T: Clone> Context<T> { | |||
159 | check_assist( | 272 | check_assist( |
160 | generate_getter, | 273 | generate_getter, |
161 | r#" | 274 | r#" |
162 | struct Context<T: Clone> { | 275 | struct Context { |
163 | data: T, | 276 | data: Data, |
164 | cou$0nt: usize, | 277 | cou$0nt: usize, |
165 | } | 278 | } |
166 | 279 | ||
167 | impl<T: Clone> Context<T> { | 280 | impl Context { |
168 | /// Get a reference to the context's data. | 281 | /// Get a reference to the context's data. |
169 | fn data(&self) -> &T { | 282 | fn data(&self) -> &Data { |
170 | &self.data | 283 | &self.data |
171 | } | 284 | } |
172 | }"#, | 285 | } |
286 | "#, | ||
173 | r#" | 287 | r#" |
174 | struct Context<T: Clone> { | 288 | struct Context { |
175 | data: T, | 289 | data: Data, |
176 | count: usize, | 290 | count: usize, |
177 | } | 291 | } |
178 | 292 | ||
179 | impl<T: Clone> Context<T> { | 293 | impl Context { |
180 | /// Get a reference to the context's data. | 294 | /// Get a reference to the context's data. |
181 | fn data(&self) -> &T { | 295 | fn data(&self) -> &Data { |
182 | &self.data | 296 | &self.data |
183 | } | 297 | } |
184 | 298 | ||
185 | /// Get a reference to the context's count. | 299 | /// Get a reference to the context's count. |
186 | fn count(&self) -> &usize { | 300 | fn $0count(&self) -> &usize { |
187 | &self.count | 301 | &self.count |
188 | } | 302 | } |
189 | }"#, | 303 | } |
304 | "#, | ||
305 | ); | ||
306 | } | ||
307 | |||
308 | #[test] | ||
309 | fn test_special_cases() { | ||
310 | cov_mark::check!(useless_type_special_case); | ||
311 | check_assist( | ||
312 | generate_getter, | ||
313 | r#" | ||
314 | struct S { foo: $0String } | ||
315 | "#, | ||
316 | r#" | ||
317 | struct S { foo: String } | ||
318 | |||
319 | impl S { | ||
320 | /// Get a reference to the s's foo. | ||
321 | fn $0foo(&self) -> &str { | ||
322 | self.foo.as_str() | ||
323 | } | ||
324 | } | ||
325 | "#, | ||
326 | ); | ||
327 | check_assist( | ||
328 | generate_getter, | ||
329 | r#" | ||
330 | struct S { foo: $0Box<Sweets> } | ||
331 | "#, | ||
332 | r#" | ||
333 | struct S { foo: Box<Sweets> } | ||
334 | |||
335 | impl S { | ||
336 | /// Get a reference to the s's foo. | ||
337 | fn $0foo(&self) -> &Sweets { | ||
338 | self.foo.as_ref() | ||
339 | } | ||
340 | } | ||
341 | "#, | ||
342 | ); | ||
343 | check_assist( | ||
344 | generate_getter, | ||
345 | r#" | ||
346 | struct S { foo: $0Vec<()> } | ||
347 | "#, | ||
348 | r#" | ||
349 | struct S { foo: Vec<()> } | ||
350 | |||
351 | impl S { | ||
352 | /// Get a reference to the s's foo. | ||
353 | fn $0foo(&self) -> &[()] { | ||
354 | self.foo.as_slice() | ||
355 | } | ||
356 | } | ||
357 | "#, | ||
358 | ); | ||
359 | check_assist( | ||
360 | generate_getter, | ||
361 | r#" | ||
362 | struct S { foo: $0Option<Failure> } | ||
363 | "#, | ||
364 | r#" | ||
365 | struct S { foo: Option<Failure> } | ||
366 | |||
367 | impl S { | ||
368 | /// Get a reference to the s's foo. | ||
369 | fn $0foo(&self) -> Option<&Failure> { | ||
370 | self.foo.as_ref() | ||
371 | } | ||
372 | } | ||
373 | "#, | ||
190 | ); | 374 | ); |
191 | } | 375 | } |
192 | } | 376 | } |
diff --git a/crates/ide_assists/src/handlers/generate_getter_mut.rs b/crates/ide_assists/src/handlers/generate_getter_mut.rs deleted file mode 100644 index 821c2eed5..000000000 --- a/crates/ide_assists/src/handlers/generate_getter_mut.rs +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | use stdx::{format_to, to_lower_snake_case}; | ||
2 | use syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; | ||
3 | |||
4 | use crate::{ | ||
5 | utils::{find_impl_block_end, find_struct_impl, generate_impl_text}, | ||
6 | AssistContext, AssistId, AssistKind, Assists, GroupLabel, | ||
7 | }; | ||
8 | |||
9 | // Assist: generate_getter_mut | ||
10 | // | ||
11 | // Generate a mut getter method. | ||
12 | // | ||
13 | // ``` | ||
14 | // struct Person { | ||
15 | // nam$0e: String, | ||
16 | // } | ||
17 | // ``` | ||
18 | // -> | ||
19 | // ``` | ||
20 | // struct Person { | ||
21 | // name: String, | ||
22 | // } | ||
23 | // | ||