diff options
58 files changed, 6104 insertions, 5836 deletions
diff --git a/.gitattributes b/.gitattributes index e749e1dc9..4cd50e481 100644 --- a/.gitattributes +++ b/.gitattributes | |||
@@ -1,2 +1,6 @@ | |||
1 | * text=auto eol=lf | 1 | * text=auto eol=lf |
2 | crates/ra_syntax/test_data/** -text eof=LF | 2 | crates/ra_syntax/test_data/** -text eof=LF |
3 | # Older git versions try to fix line endings on images, this prevents it. | ||
4 | *.png binary | ||
5 | *.jpg binary | ||
6 | *.ico binary | ||
diff --git a/Cargo.lock b/Cargo.lock index e0ba7b688..029698808 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -126,9 +126,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | |||
126 | 126 | ||
127 | [[package]] | 127 | [[package]] |
128 | name = "chalk-derive" | 128 | name = "chalk-derive" |
129 | version = "0.17.0" | 129 | version = "0.18.0" |
130 | source = "registry+https://github.com/rust-lang/crates.io-index" | 130 | source = "registry+https://github.com/rust-lang/crates.io-index" |
131 | checksum = "9396f12a23b1a40d5019aa81bc0cbd7ccd2c9736d6bc4afc95868533c2346dcb" | 131 | checksum = "eea3a22f0c30b2504ac4ab58934dac0d00b92a4d7788df32795cabca24c3f929" |
132 | dependencies = [ | 132 | dependencies = [ |
133 | "proc-macro2", | 133 | "proc-macro2", |
134 | "quote", | 134 | "quote", |
@@ -138,9 +138,9 @@ dependencies = [ | |||
138 | 138 | ||
139 | [[package]] | 139 | [[package]] |
140 | name = "chalk-ir" | 140 | name = "chalk-ir" |
141 | version = "0.17.0" | 141 | version = "0.18.0" |
142 | source = "registry+https://github.com/rust-lang/crates.io-index" | 142 | source = "registry+https://github.com/rust-lang/crates.io-index" |
143 | checksum = "87e9c67d500717d65ede27affb7ae40efe240d86fbefff1006fe0ffb62d4caf9" | 143 | checksum = "fb617b643e145e3b151502799e91a9625dd5daf1cf05dc2cb821bc75ae0c9cbd" |
144 | dependencies = [ | 144 | dependencies = [ |
145 | "chalk-derive", | 145 | "chalk-derive", |
146 | "lazy_static", | 146 | "lazy_static", |
@@ -148,9 +148,9 @@ dependencies = [ | |||
148 | 148 | ||
149 | [[package]] | 149 | [[package]] |
150 | name = "chalk-recursive" | 150 | name = "chalk-recursive" |
151 | version = "0.17.0" | 151 | version = "0.18.0" |
152 | source = "registry+https://github.com/rust-lang/crates.io-index" | 152 | source = "registry+https://github.com/rust-lang/crates.io-index" |
153 | checksum = "a8fd2ac0fc06c857b95614d229bbe8ea317d1d94a7e8b9442a3f05c9a2c2d5f4" | 153 | checksum = "d280565c8eefbf9b2bc615df49c7dfd971faad37774bf65734e626fd23864bd6" |
154 | dependencies = [ | 154 | dependencies = [ |
155 | "chalk-derive", | 155 | "chalk-derive", |
156 | "chalk-ir", | 156 | "chalk-ir", |
@@ -161,9 +161,9 @@ dependencies = [ | |||
161 | 161 | ||
162 | [[package]] | 162 | [[package]] |
163 | name = "chalk-solve" | 163 | name = "chalk-solve" |
164 | version = "0.17.0" | 164 | version = "0.18.0" |
165 | source = "registry+https://github.com/rust-lang/crates.io-index" | 165 | source = "registry+https://github.com/rust-lang/crates.io-index" |
166 | checksum = "2a79166f2405c1e51eadcc1344f5ee833c7b391532dd78f64a0731a9a123cc58" | 166 | checksum = "be906fbca3f3077dce0e76d9864771d0f450c946af0d86b569fb9504148a065a" |
167 | dependencies = [ | 167 | dependencies = [ |
168 | "chalk-derive", | 168 | "chalk-derive", |
169 | "chalk-ir", | 169 | "chalk-ir", |
@@ -206,20 +206,6 @@ dependencies = [ | |||
206 | ] | 206 | ] |
207 | 207 | ||
208 | [[package]] | 208 | [[package]] |
209 | name = "console" | ||
210 | version = "0.11.3" | ||
211 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
212 | checksum = "8c0994e656bba7b922d8dd1245db90672ffb701e684e45be58f20719d69abc5a" | ||
213 | dependencies = [ | ||
214 | "encode_unicode", | ||
215 | "lazy_static", | ||
216 | "libc", | ||
217 | "terminal_size", | ||
218 | "termios", | ||
219 | "winapi 0.3.9", | ||
220 | ] | ||
221 | |||
222 | [[package]] | ||
223 | name = "crc32fast" | 209 | name = "crc32fast" |
224 | version = "1.2.0" | 210 | version = "1.2.0" |
225 | source = "registry+https://github.com/rust-lang/crates.io-index" | 211 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -230,12 +216,12 @@ dependencies = [ | |||
230 | 216 | ||
231 | [[package]] | 217 | [[package]] |
232 | name = "crossbeam-channel" | 218 | name = "crossbeam-channel" |
233 | version = "0.4.2" | 219 | version = "0.4.3" |
234 | source = "registry+https://github.com/rust-lang/crates.io-index" | 220 | source = "registry+https://github.com/rust-lang/crates.io-index" |
235 | checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" | 221 | checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" |
236 | dependencies = [ | 222 | dependencies = [ |
223 | "cfg-if", | ||
237 | "crossbeam-utils", | 224 | "crossbeam-utils", |
238 | "maybe-uninit", | ||
239 | ] | 225 | ] |
240 | 226 | ||
241 | [[package]] | 227 | [[package]] |
@@ -299,12 +285,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
299 | checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | 285 | checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" |
300 | 286 | ||
301 | [[package]] | 287 | [[package]] |
302 | name = "dtoa" | ||
303 | version = "0.4.6" | ||
304 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
305 | checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" | ||
306 | |||
307 | [[package]] | ||
308 | name = "either" | 288 | name = "either" |
309 | version = "1.5.3" | 289 | version = "1.5.3" |
310 | source = "registry+https://github.com/rust-lang/crates.io-index" | 290 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -320,12 +300,6 @@ dependencies = [ | |||
320 | ] | 300 | ] |
321 | 301 | ||
322 | [[package]] | 302 | [[package]] |
323 | name = "encode_unicode" | ||
324 | version = "0.3.6" | ||
325 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
326 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | ||
327 | |||
328 | [[package]] | ||
329 | name = "env_logger" | 303 | name = "env_logger" |
330 | version = "0.7.1" | 304 | version = "0.7.1" |
331 | source = "registry+https://github.com/rust-lang/crates.io-index" | 305 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -386,12 +360,6 @@ dependencies = [ | |||
386 | ] | 360 | ] |
387 | 361 | ||
388 | [[package]] | 362 | [[package]] |
389 | name = "fs_extra" | ||
390 | version = "1.1.0" | ||
391 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
392 | checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" | ||
393 | |||
394 | [[package]] | ||
395 | name = "fsevent" | 363 | name = "fsevent" |
396 | version = "2.0.2" | 364 | version = "2.0.2" |
397 | source = "registry+https://github.com/rust-lang/crates.io-index" | 365 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -538,20 +506,6 @@ dependencies = [ | |||
538 | ] | 506 | ] |
539 | 507 | ||
540 | [[package]] | 508 | [[package]] |
541 | name = "insta" | ||
542 | version = "0.16.1" | ||
543 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
544 | checksum = "617e921abc813f96a3b00958c079e7bf1e2db998f8a04f1546dd967373a418ee" | ||
545 | dependencies = [ | ||
546 | "console", | ||
547 | "difference", | ||
548 | "lazy_static", | ||
549 | "serde", | ||
550 | "serde_json", | ||
551 | "serde_yaml", | ||
552 | ] | ||
553 | |||
554 | [[package]] | ||
555 | name = "instant" | 509 | name = "instant" |
556 | version = "0.1.6" | 510 | version = "0.1.6" |
557 | source = "registry+https://github.com/rust-lang/crates.io-index" | 511 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -582,38 +536,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
582 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" | 536 | checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" |
583 | 537 | ||
584 | [[package]] | 538 | [[package]] |
585 | name = "jemalloc-ctl" | ||
586 | version = "0.3.3" | ||
587 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
588 | checksum = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7" | ||
589 | dependencies = [ | ||
590 | "jemalloc-sys", | ||
591 | "libc", | ||
592 | "paste", | ||
593 | ] | ||
594 | |||
595 | [[package]] | ||
596 | name = "jemalloc-sys" | ||
597 | version = "0.3.2" | ||
598 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
599 | checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" | ||
600 | dependencies = [ | ||
601 | "cc", | ||
602 | "fs_extra", | ||
603 | "libc", | ||
604 | ] | ||
605 | |||
606 | [[package]] | ||
607 | name = "jemallocator" | ||
608 | version = "0.3.2" | ||
609 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
610 | checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69" | ||
611 | dependencies = [ | ||
612 | "jemalloc-sys", | ||
613 | "libc", | ||
614 | ] | ||
615 | |||
616 | [[package]] | ||
617 | name = "jod-thread" | 539 | name = "jod-thread" |
618 | version = "0.1.2" | 540 | version = "0.1.2" |
619 | source = "registry+https://github.com/rust-lang/crates.io-index" | 541 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -666,12 +588,6 @@ dependencies = [ | |||
666 | ] | 588 | ] |
667 | 589 | ||
668 | [[package]] | 590 | [[package]] |
669 | name = "linked-hash-map" | ||
670 | version = "0.5.3" | ||
671 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
672 | checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" | ||
673 | |||
674 | [[package]] | ||
675 | name = "lock_api" | 591 | name = "lock_api" |
676 | version = "0.4.1" | 592 | version = "0.4.1" |
677 | source = "registry+https://github.com/rust-lang/crates.io-index" | 593 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -703,9 +619,9 @@ dependencies = [ | |||
703 | 619 | ||
704 | [[package]] | 620 | [[package]] |
705 | name = "lsp-types" | 621 | name = "lsp-types" |
706 | version = "0.77.0" | 622 | version = "0.78.0" |
707 | source = "registry+https://github.com/rust-lang/crates.io-index" | 623 | source = "registry+https://github.com/rust-lang/crates.io-index" |
708 | checksum = "897c6c8930fbf12b67deffc83729287bb379dd5e5a4bd0ae2d81eff8d6503db6" | 624 | checksum = "d2e6cf68e3492cfa2035f0382c1da1b6ab045db0320feca505b86b4f13d66c27" |
709 | dependencies = [ | 625 | dependencies = [ |
710 | "base64", | 626 | "base64", |
711 | "bitflags", | 627 | "bitflags", |
@@ -921,25 +837,6 @@ dependencies = [ | |||
921 | ] | 837 | ] |
922 | 838 | ||
923 | [[package]] | 839 | [[package]] |
924 | name = "paste" | ||
925 | version = "0.1.18" | ||
926 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
927 | checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" | ||
928 | dependencies = [ | ||
929 | "paste-impl", | ||
930 | "proc-macro-hack", | ||
931 | ] | ||
932 | |||
933 | [[package]] | ||
934 | name = "paste-impl" | ||
935 | version = "0.1.18" | ||
936 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
937 | checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" | ||
938 | dependencies = [ | ||
939 | "proc-macro-hack", | ||
940 | ] | ||
941 | |||
942 | [[package]] | ||
943 | name = "paths" | 840 | name = "paths" |
944 | version = "0.1.0" | 841 | version = "0.1.0" |
945 | 842 | ||
@@ -978,12 +875,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
978 | checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" | 875 | checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" |
979 | 876 | ||
980 | [[package]] | 877 | [[package]] |
981 | name = "proc-macro-hack" | ||
982 | version = "0.5.16" | ||
983 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
984 | checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" | ||
985 | |||
986 | [[package]] | ||
987 | name = "proc-macro2" | 878 | name = "proc-macro2" |
988 | version = "1.0.19" | 879 | version = "1.0.19" |
989 | source = "registry+https://github.com/rust-lang/crates.io-index" | 880 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1128,7 +1019,6 @@ dependencies = [ | |||
1128 | "chalk-solve", | 1019 | "chalk-solve", |
1129 | "ena", | 1020 | "ena", |
1130 | "expect", | 1021 | "expect", |
1131 | "insta", | ||
1132 | "itertools", | 1022 | "itertools", |
1133 | "log", | 1023 | "log", |
1134 | "ra_arena", | 1024 | "ra_arena", |
@@ -1187,7 +1077,7 @@ dependencies = [ | |||
1187 | "ra_text_edit", | 1077 | "ra_text_edit", |
1188 | "rayon", | 1078 | "rayon", |
1189 | "rustc-hash", | 1079 | "rustc-hash", |
1190 | "superslice", | 1080 | "stdx", |
1191 | "test_utils", | 1081 | "test_utils", |
1192 | ] | 1082 | ] |
1193 | 1083 | ||
@@ -1245,9 +1135,8 @@ name = "ra_prof" | |||
1245 | version = "0.1.0" | 1135 | version = "0.1.0" |
1246 | dependencies = [ | 1136 | dependencies = [ |
1247 | "backtrace", | 1137 | "backtrace", |
1248 | "jemalloc-ctl", | 1138 | "cfg-if", |
1249 | "jemallocator", | 1139 | "libc", |
1250 | "mimalloc", | ||
1251 | "once_cell", | 1140 | "once_cell", |
1252 | "ra_arena", | 1141 | "ra_arena", |
1253 | ] | 1142 | ] |
@@ -1472,6 +1361,7 @@ dependencies = [ | |||
1472 | "log", | 1361 | "log", |
1473 | "lsp-server", | 1362 | "lsp-server", |
1474 | "lsp-types", | 1363 | "lsp-types", |
1364 | "mimalloc", | ||
1475 | "parking_lot", | 1365 | "parking_lot", |
1476 | "pico-args", | 1366 | "pico-args", |
1477 | "ra_cfg", | 1367 | "ra_cfg", |
@@ -1506,9 +1396,9 @@ dependencies = [ | |||
1506 | 1396 | ||
1507 | [[package]] | 1397 | [[package]] |
1508 | name = "rustc-ap-rustc_lexer" | 1398 | name = "rustc-ap-rustc_lexer" |
1509 | version = "666.0.0" | 1399 | version = "669.0.0" |
1510 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1511 | checksum = "4e00c526f9f8430ea4cd2178d25b02bfc7debe6677350c57292f92f50e65d2fe" | 1401 | checksum = "456af5f09c006cf6c22c1a433ee0232c4bb74bdc6c647a010166a47c94ed2a63" |
1512 | dependencies = [ | 1402 | dependencies = [ |
1513 | "unicode-xid", | 1403 | "unicode-xid", |
1514 | ] | 1404 | ] |
@@ -1660,18 +1550,6 @@ dependencies = [ | |||
1660 | ] | 1550 | ] |
1661 | 1551 | ||
1662 | [[package]] | 1552 | [[package]] |
1663 | name = "serde_yaml" | ||
1664 | version = "0.8.13" | ||
1665 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1666 | checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" | ||
1667 | dependencies = [ | ||
1668 | "dtoa", | ||
1669 | "linked-hash-map", | ||
1670 | "serde", | ||
1671 | "yaml-rust", | ||
1672 | ] | ||
1673 | |||
1674 | [[package]] | ||
1675 | name = "sharded-slab" | 1553 | name = "sharded-slab" |
1676 | version = "0.0.9" | 1554 | version = "0.0.9" |
1677 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1706,12 +1584,6 @@ name = "stdx" | |||
1706 | version = "0.1.0" | 1584 | version = "0.1.0" |
1707 | 1585 | ||
1708 | [[package]] | 1586 | [[package]] |
1709 | name = "superslice" | ||
1710 | version = "1.0.0" | ||
1711 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1712 | checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | ||
1713 | |||
1714 | [[package]] | ||
1715 | name = "syn" | 1587 | name = "syn" |
1716 | version = "1.0.35" | 1588 | version = "1.0.35" |
1717 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1758,25 +1630,6 @@ dependencies = [ | |||
1758 | ] | 1630 | ] |
1759 | 1631 | ||
1760 | [[package]] | 1632 | [[package]] |
1761 | name = "terminal_size" | ||
1762 | version = "0.1.13" | ||
1763 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1764 | checksum = "9a14cd9f8c72704232f0bfc8455c0e861f0ad4eb60cc9ec8a170e231414c1e13" | ||
1765 | dependencies = [ | ||
1766 | "libc", | ||
1767 | "winapi 0.3.9", | ||
1768 | ] | ||
1769 | |||
1770 | [[package]] | ||
1771 | name = "termios" | ||
1772 | version = "0.3.2" | ||
1773 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1774 | checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2" | ||
1775 | dependencies = [ | ||
1776 | "libc", | ||
1777 | ] | ||
1778 | |||
1779 | [[package]] | ||
1780 | name = "test_utils" | 1633 | name = "test_utils" |
1781 | version = "0.1.0" | 1634 | version = "0.1.0" |
1782 | dependencies = [ | 1635 | dependencies = [ |
@@ -2065,12 +1918,3 @@ dependencies = [ | |||
2065 | "quote", | 1918 | "quote", |
2066 | "walkdir", | 1919 | "walkdir", |
2067 | ] | 1920 | ] |
2068 | |||
2069 | [[package]] | ||
2070 | name = "yaml-rust" | ||
2071 | version = "0.4.4" | ||
2072 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
2073 | checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" | ||
2074 | dependencies = [ | ||
2075 | "linked-hash-map", | ||
2076 | ] | ||
diff --git a/crates/ra_assists/src/handlers/change_return_type_to_result.rs b/crates/ra_assists/src/handlers/change_return_type_to_result.rs index 24e5f6963..def00f7d8 100644 --- a/crates/ra_assists/src/handlers/change_return_type_to_result.rs +++ b/crates/ra_assists/src/handlers/change_return_type_to_result.rs | |||
@@ -36,7 +36,7 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex | |||
36 | 36 | ||
37 | acc.add( | 37 | acc.add( |
38 | AssistId("change_return_type_to_result", AssistKind::RefactorRewrite), | 38 | AssistId("change_return_type_to_result", AssistKind::RefactorRewrite), |
39 | "Change return type to Result", | 39 | "Wrap return type in Result", |
40 | type_ref.syntax().text_range(), | 40 | type_ref.syntax().text_range(), |
41 | |builder| { | 41 | |builder| { |
42 | let mut tail_return_expr_collector = TailReturnCollector::new(); | 42 | let mut tail_return_expr_collector = TailReturnCollector::new(); |
diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs index 481baf1a4..098adf078 100644 --- a/crates/ra_assists/src/handlers/extract_variable.rs +++ b/crates/ra_assists/src/handlers/extract_variable.rs | |||
@@ -2,7 +2,6 @@ use ra_syntax::{ | |||
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | SyntaxKind::{ | 3 | SyntaxKind::{ |
4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, | 4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, |
5 | WHITESPACE, | ||
6 | }, | 5 | }, |
7 | SyntaxNode, | 6 | SyntaxNode, |
8 | }; | 7 | }; |
@@ -36,22 +35,20 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
36 | mark::hit!(extract_var_in_comment_is_not_applicable); | 35 | mark::hit!(extract_var_in_comment_is_not_applicable); |
37 | return None; | 36 | return None; |
38 | } | 37 | } |
39 | let expr = node.ancestors().find_map(valid_target_expr)?; | 38 | let to_extract = node.ancestors().find_map(valid_target_expr)?; |
40 | let (anchor_stmt, wrap_in_block) = anchor_stmt(expr.clone())?; | 39 | let anchor = Anchor::from(&to_extract)?; |
41 | let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?.clone(); | 40 | let indent = anchor.syntax().prev_sibling_or_token()?.as_token()?.clone(); |
42 | if indent.kind() != WHITESPACE { | 41 | let target = to_extract.syntax().text_range(); |
43 | return None; | ||
44 | } | ||
45 | let target = expr.syntax().text_range(); | ||
46 | acc.add( | 42 | acc.add( |
47 | AssistId("extract_variable", AssistKind::RefactorExtract), | 43 | AssistId("extract_variable", AssistKind::RefactorExtract), |
48 | "Extract into variable", | 44 | "Extract into variable", |
49 | target, | 45 | target, |
50 | move |edit| { | 46 | move |edit| { |
51 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | 47 | let field_shorthand = |
52 | Some(field) => field.name_ref(), | 48 | match to_extract.syntax().parent().and_then(ast::RecordField::cast) { |
53 | None => None, | 49 | Some(field) => field.name_ref(), |
54 | }; | 50 | None => None, |
51 | }; | ||
55 | 52 | ||
56 | let mut buf = String::new(); | 53 | let mut buf = String::new(); |
57 | 54 | ||
@@ -60,26 +57,20 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
60 | None => "var_name".to_string(), | 57 | None => "var_name".to_string(), |
61 | }; | 58 | }; |
62 | let expr_range = match &field_shorthand { | 59 | let expr_range = match &field_shorthand { |
63 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), | 60 | Some(it) => it.syntax().text_range().cover(to_extract.syntax().text_range()), |
64 | None => expr.syntax().text_range(), | 61 | None => to_extract.syntax().text_range(), |
65 | }; | 62 | }; |
66 | 63 | ||
67 | if wrap_in_block { | 64 | if let Anchor::WrapInBlock(_) = anchor { |
68 | format_to!(buf, "{{ let {} = ", var_name); | 65 | format_to!(buf, "{{ let {} = ", var_name); |
69 | } else { | 66 | } else { |
70 | format_to!(buf, "let {} = ", var_name); | 67 | format_to!(buf, "let {} = ", var_name); |
71 | }; | 68 | }; |
72 | format_to!(buf, "{}", expr.syntax()); | 69 | format_to!(buf, "{}", to_extract.syntax()); |
73 | 70 | ||
74 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 71 | if let Anchor::Replace(stmt) = anchor { |
75 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { | ||
76 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) | ||
77 | } else { | ||
78 | false | ||
79 | }; | ||
80 | if is_full_stmt { | ||
81 | mark::hit!(test_extract_var_expr_stmt); | 72 | mark::hit!(test_extract_var_expr_stmt); |
82 | if full_stmt.unwrap().semicolon_token().is_none() { | 73 | if stmt.semicolon_token().is_none() { |
83 | buf.push_str(";"); | 74 | buf.push_str(";"); |
84 | } | 75 | } |
85 | match ctx.config.snippet_cap { | 76 | match ctx.config.snippet_cap { |
@@ -107,7 +98,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
107 | } | 98 | } |
108 | 99 | ||
109 | edit.replace(expr_range, var_name.clone()); | 100 | edit.replace(expr_range, var_name.clone()); |
110 | let offset = anchor_stmt.text_range().start(); | 101 | let offset = anchor.syntax().text_range().start(); |
111 | match ctx.config.snippet_cap { | 102 | match ctx.config.snippet_cap { |
112 | Some(cap) => { | 103 | Some(cap) => { |
113 | let snip = | 104 | let snip = |
@@ -117,8 +108,8 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
117 | None => edit.insert(offset, buf), | 108 | None => edit.insert(offset, buf), |
118 | } | 109 | } |
119 | 110 | ||
120 | if wrap_in_block { | 111 | if let Anchor::WrapInBlock(_) = anchor { |
121 | edit.insert(anchor_stmt.text_range().end(), " }"); | 112 | edit.insert(anchor.syntax().text_range().end(), " }"); |
122 | } | 113 | } |
123 | }, | 114 | }, |
124 | ) | 115 | ) |
@@ -138,32 +129,48 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> { | |||
138 | } | 129 | } |
139 | } | 130 | } |
140 | 131 | ||
141 | /// Returns the syntax node which will follow the freshly extractd var | 132 | enum Anchor { |
142 | /// and a boolean indicating whether we have to wrap it within a { } block | 133 | Before(SyntaxNode), |
143 | /// to produce correct code. | 134 | Replace(ast::ExprStmt), |
144 | /// It can be a statement, the last in a block expression or a wanna be block | 135 | WrapInBlock(SyntaxNode), |
145 | /// expression like a lambda or match arm. | 136 | } |
146 | fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { | 137 | |
147 | expr.syntax().ancestors().find_map(|node| { | 138 | impl Anchor { |
148 | if let Some(expr) = node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) { | 139 | fn from(to_extract: &ast::Expr) -> Option<Anchor> { |
149 | if expr.syntax() == &node { | 140 | to_extract.syntax().ancestors().find_map(|node| { |
150 | mark::hit!(test_extract_var_last_expr); | 141 | if let Some(expr) = |
151 | return Some((node, false)); | 142 | node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) |
143 | { | ||
144 | if expr.syntax() == &node { | ||
145 | mark::hit!(test_extract_var_last_expr); | ||
146 | return Some(Anchor::Before(node)); | ||
147 | } | ||
152 | } | 148 | } |
153 | } | ||
154 | 149 | ||
155 | if let Some(parent) = node.parent() { | 150 | if let Some(parent) = node.parent() { |
156 | if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR { | 151 | if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR { |
157 | return Some((node, true)); | 152 | return Some(Anchor::WrapInBlock(node)); |
153 | } | ||
158 | } | 154 | } |
159 | } | ||
160 | 155 | ||
161 | if ast::Stmt::cast(node.clone()).is_some() { | 156 | if let Some(stmt) = ast::Stmt::cast(node.clone()) { |
162 | return Some((node, false)); | 157 | if let ast::Stmt::ExprStmt(stmt) = stmt { |
163 | } | 158 | if stmt.expr().as_ref() == Some(to_extract) { |
159 | return Some(Anchor::Replace(stmt)); | ||
160 | } | ||
161 | } | ||
162 | return Some(Anchor::Before(node)); | ||
163 | } | ||
164 | None | ||
165 | }) | ||
166 | } | ||
164 | 167 | ||
165 | None | 168 | fn syntax(&self) -> &SyntaxNode { |
166 | }) | 169 | match self { |
170 | Anchor::Before(it) | Anchor::WrapInBlock(it) => it, | ||
171 | Anchor::Replace(stmt) => stmt.syntax(), | ||
172 | } | ||
173 | } | ||
167 | } | 174 | } |
168 | 175 | ||
169 | #[cfg(test)] | 176 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs index e212557c8..1d3ed3c6a 100644 --- a/crates/ra_assists/src/handlers/fix_visibility.rs +++ b/crates/ra_assists/src/handlers/fix_visibility.rs | |||
@@ -3,6 +3,7 @@ use ra_db::FileId; | |||
3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; | 3 | use ra_syntax::{ast, AstNode, TextRange, TextSize}; |
4 | 4 | ||
5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; | 5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; |
6 | use ast::VisibilityOwner; | ||
6 | 7 | ||
7 | // FIXME: this really should be a fix for diagnostic, rather than an assist. | 8 | // FIXME: this really should be a fix for diagnostic, rather than an assist. |
8 | 9 | ||
@@ -48,7 +49,8 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
48 | return None; | 49 | return None; |
49 | }; | 50 | }; |
50 | 51 | ||
51 | let (offset, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?; | 52 | let (offset, current_visibility, target, target_file, target_name) = |
53 | target_data_for_def(ctx.db(), def)?; | ||
52 | 54 | ||
53 | let missing_visibility = | 55 | let missing_visibility = |
54 | if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" }; | 56 | if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" }; |
@@ -61,8 +63,20 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O | |||
61 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { | 63 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
62 | builder.edit_file(target_file); | 64 | builder.edit_file(target_file); |
63 | match ctx.config.snippet_cap { | 65 | match ctx.config.snippet_cap { |
64 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 66 | Some(cap) => match current_visibility { |
65 | None => builder.insert(offset, format!("{} ", missing_visibility)), | 67 | Some(current_visibility) => builder.replace_snippet( |
68 | cap, | ||
69 | current_visibility.syntax().text_range(), | ||
70 | format!("$0{}", missing_visibility), | ||
71 | ), | ||
72 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | ||
73 | }, | ||
74 | None => match current_visibility { | ||
75 | Some(current_visibility) => { | ||
76 | builder.replace(current_visibility.syntax().text_range(), missing_visibility) | ||
77 | } | ||
78 | None => builder.insert(offset, format!("{} ", missing_visibility)), | ||
79 | }, | ||
66 | } | 80 | } |
67 | }) | 81 | }) |
68 | } | 82 | } |
@@ -82,14 +96,14 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
82 | let target_module = parent.module(ctx.db()); | 96 | let target_module = parent.module(ctx.db()); |
83 | 97 | ||
84 | let in_file_source = record_field_def.source(ctx.db()); | 98 | let in_file_source = record_field_def.source(ctx.db()); |
85 | let (offset, target) = match in_file_source.value { | 99 | let (offset, current_visibility, target) = match in_file_source.value { |
86 | hir::FieldSource::Named(it) => { | 100 | hir::FieldSource::Named(it) => { |
87 | let s = it.syntax(); | 101 | let s = it.syntax(); |
88 | (vis_offset(s), s.text_range()) | 102 | (vis_offset(s), it.visibility(), s.text_range()) |
89 | } | 103 | } |
90 | hir::FieldSource::Pos(it) => { | 104 | hir::FieldSource::Pos(it) => { |
91 | let s = it.syntax(); | 105 | let s = it.syntax(); |
92 | (vis_offset(s), s.text_range()) | 106 | (vis_offset(s), it.visibility(), s.text_range()) |
93 | } | 107 | } |
94 | }; | 108 | }; |
95 | 109 | ||
@@ -104,8 +118,20 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
104 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { | 118 | acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| { |
105 | builder.edit_file(target_file); | 119 | builder.edit_file(target_file); |
106 | match ctx.config.snippet_cap { | 120 | match ctx.config.snippet_cap { |
107 | Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | 121 | Some(cap) => match current_visibility { |
108 | None => builder.insert(offset, format!("{} ", missing_visibility)), | 122 | Some(current_visibility) => builder.replace_snippet( |
123 | cap, | ||
124 | dbg!(current_visibility.syntax()).text_range(), | ||
125 | format!("$0{}", missing_visibility), | ||
126 | ), | ||
127 | None => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)), | ||
128 | }, | ||
129 | None => match current_visibility { | ||
130 | Some(current_visibility) => { | ||
131 | builder.replace(current_visibility.syntax().text_range(), missing_visibility) | ||
132 | } | ||
133 | None => builder.insert(offset, format!("{} ", missing_visibility)), | ||
134 | }, | ||
109 | } | 135 | } |
110 | }) | 136 | }) |
111 | } | 137 | } |
@@ -113,24 +139,30 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
113 | fn target_data_for_def( | 139 | fn target_data_for_def( |
114 | db: &dyn HirDatabase, | 140 | db: &dyn HirDatabase, |
115 | def: hir::ModuleDef, | 141 | def: hir::ModuleDef, |
116 | ) -> Option<(TextSize, TextRange, FileId, Option<hir::Name>)> { | 142 | ) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId, Option<hir::Name>)> { |
117 | fn offset_target_and_file_id<S, Ast>( | 143 | fn offset_target_and_file_id<S, Ast>( |
118 | db: &dyn HirDatabase, | 144 | db: &dyn HirDatabase, |
119 | x: S, | 145 | x: S, |
120 | ) -> (TextSize, TextRange, FileId) | 146 | ) -> (TextSize, Option<ast::Visibility>, TextRange, FileId) |
121 | where | 147 | where |
122 | S: HasSource<Ast = Ast>, | 148 | S: HasSource<Ast = Ast>, |
123 | Ast: AstNode, | 149 | Ast: AstNode + ast::VisibilityOwner, |
124 | { | 150 | { |
125 | let source = x.source(db); | 151 | let source = x.source(db); |
126 | let in_file_syntax = source.syntax(); | 152 | let in_file_syntax = source.syntax(); |
127 | let file_id = in_file_syntax.file_id; | 153 | let file_id = in_file_syntax.file_id; |
128 | let syntax = in_file_syntax.value; | 154 | let syntax = in_file_syntax.value; |
129 | (vis_offset(syntax), syntax.text_range(), file_id.original_file(db.upcast())) | 155 | let current_visibility = source.value.visibility(); |
156 | ( | ||
157 | vis_offset(syntax), | ||
158 | current_visibility, | ||
159 | syntax.text_range(), | ||
160 | file_id.original_file(db.upcast()), | ||
161 | ) | ||
130 | } | 162 | } |
131 | 163 | ||
132 | let target_name; | 164 | let target_name; |
133 | let (offset, target, target_file) = match def { | 165 | let (offset, current_visibility, target, target_file) = match def { |
134 | hir::ModuleDef::Function(f) => { | 166 | hir::ModuleDef::Function(f) => { |
135 | target_name = Some(f.name(db)); | 167 | target_name = Some(f.name(db)); |
136 | offset_target_and_file_id(db, f) | 168 | offset_target_and_file_id(db, f) |
@@ -164,13 +196,13 @@ fn target_data_for_def( | |||
164 | let in_file_source = m.declaration_source(db)?; | 196 | let in_file_source = m.declaration_source(db)?; |
165 | let file_id = in_file_source.file_id.original_file(db.upcast()); | 197 | let file_id = in_file_source.file_id.original_file(db.upcast()); |
166 | let syntax = in_file_source.value.syntax(); | 198 | let syntax = in_file_source.value.syntax(); |
167 | (vis_offset(syntax), syntax.text_range(), file_id) | 199 | (vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id) |
168 | } | 200 | } |
169 | // Enum variants can't be private, we can't modify builtin types | 201 | // Enum variants can't be private, we can't modify builtin types |
170 | hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None, | 202 | hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None, |
171 | }; | 203 | }; |
172 | 204 | ||
173 | Some((offset, target, target_file, target_name)) | 205 | Some((offset, current_visibility, target, target_file, target_name)) |
174 | } | 206 | } |
175 | 207 | ||
176 | #[cfg(test)] | 208 | #[cfg(test)] |
@@ -523,6 +555,34 @@ struct Bar; | |||
523 | } | 555 | } |
524 | 556 | ||
525 | #[test] | 557 | #[test] |
558 | fn replaces_pub_crate_with_pub() { | ||
559 | check_assist( | ||
560 | fix_visibility, | ||
561 | r" | ||
562 | //- /main.rs crate:a deps:foo | ||
563 | foo::Bar<|> | ||
564 | //- /lib.rs crate:foo | ||
565 | pub(crate) struct Bar; | ||
566 | ", | ||
567 | r"$0pub struct Bar; | ||
568 | ", | ||
569 | ); | ||
570 | check_assist( | ||
571 | fix_visibility, | ||
572 | r" | ||
573 | //- /main.rs crate:a deps:foo | ||
574 | fn main() { | ||
575 | foo::Foo { <|>bar: () }; | ||
576 | } | ||
577 | //- /lib.rs crate:foo | ||
578 | pub struct Foo { pub(crate) bar: () } | ||
579 | ", | ||
580 | r"pub struct Foo { $0pub bar: () } | ||
581 | ", | ||
582 | ); | ||
583 | } | ||
584 | |||
585 | #[test] | ||
526 | #[ignore] | 586 | #[ignore] |
527 | // FIXME handle reexports properly | 587 | // FIXME handle reexports properly |
528 | fn fix_visibility_of_reexport() { | 588 | fn fix_visibility_of_reexport() { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 1ad92a1f8..a2b9f3e35 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -11,7 +11,7 @@ pub use hir_def::db::{ | |||
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
14 | MacroArgQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, | 14 | MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, |
15 | }; | 15 | }; |
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index beeb98559..8fee4b15e 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -36,6 +36,8 @@ pub struct ItemScope { | |||
36 | 36 | ||
37 | defs: Vec<ModuleDefId>, | 37 | defs: Vec<ModuleDefId>, |
38 | impls: Vec<ImplId>, | 38 | impls: Vec<ImplId>, |
39 | /// Traits imported via `use Trait as _;`. | ||
40 | unnamed_trait_imports: FxHashMap<TraitId, Visibility>, | ||
39 | /// Macros visible in current module in legacy textual scope | 41 | /// Macros visible in current module in legacy textual scope |
40 | /// | 42 | /// |
41 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. | 43 | /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. |
@@ -126,10 +128,13 @@ impl ItemScope { | |||
126 | } | 128 | } |
127 | 129 | ||
128 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | 130 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { |
129 | self.types.values().filter_map(|(def, _)| match def { | 131 | self.types |
130 | ModuleDefId::TraitId(t) => Some(*t), | 132 | .values() |
131 | _ => None, | 133 | .filter_map(|(def, _)| match def { |
132 | }) | 134 | ModuleDefId::TraitId(t) => Some(*t), |
135 | _ => None, | ||
136 | }) | ||
137 | .chain(self.unnamed_trait_imports.keys().copied()) | ||
133 | } | 138 | } |
134 | 139 | ||
135 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { | 140 | pub(crate) fn define_def(&mut self, def: ModuleDefId) { |
@@ -148,6 +153,14 @@ impl ItemScope { | |||
148 | self.legacy_macros.insert(name, mac); | 153 | self.legacy_macros.insert(name, mac); |
149 | } | 154 | } |
150 | 155 | ||
156 | pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { | ||
157 | self.unnamed_trait_imports.get(&tr).copied() | ||
158 | } | ||
159 | |||
160 | pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { | ||
161 | self.unnamed_trait_imports.insert(tr, vis); | ||
162 | } | ||
163 | |||
151 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { | 164 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { |
152 | let mut changed = false; | 165 | let mut changed = false; |
153 | 166 | ||
@@ -241,8 +254,12 @@ impl ItemScope { | |||
241 | changed | 254 | changed |
242 | } | 255 | } |
243 | 256 | ||
244 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { | 257 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, PerNs)> + 'a { |
245 | self.entries().map(|(name, res)| (name.clone(), res)) | 258 | self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( |
259 | self.unnamed_trait_imports | ||
260 | .iter() | ||
261 | .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), | ||
262 | ) | ||
246 | } | 263 | } |
247 | 264 | ||
248 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 265 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 5a9de3d3e..3d9b55a73 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -239,7 +239,7 @@ impl CrateDefMap { | |||
239 | entries.sort_by_key(|(name, _)| name.clone()); | 239 | entries.sort_by_key(|(name, _)| name.clone()); |
240 | 240 | ||
241 | for (name, def) in entries { | 241 | for (name, def) in entries { |
242 | format_to!(buf, "{}:", name); | 242 | format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string())); |
243 | 243 | ||
244 | if def.types.is_some() { | 244 | if def.types.is_some() { |
245 | buf.push_str(" t"); | 245 | buf.push_str(" t"); |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d85a86c0a..a030cab47 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -310,7 +310,7 @@ impl DefCollector<'_> { | |||
310 | if export { | 310 | if export { |
311 | self.update( | 311 | self.update( |
312 | self.def_map.root, | 312 | self.def_map.root, |
313 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 313 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
314 | Visibility::Public, | 314 | Visibility::Public, |
315 | ImportType::Named, | 315 | ImportType::Named, |
316 | ); | 316 | ); |
@@ -336,7 +336,7 @@ impl DefCollector<'_> { | |||
336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
337 | self.update( | 337 | self.update( |
338 | self.def_map.root, | 338 | self.def_map.root, |
339 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 339 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
340 | Visibility::Public, | 340 | Visibility::Public, |
341 | ImportType::Named, | 341 | ImportType::Named, |
342 | ); | 342 | ); |
@@ -534,7 +534,7 @@ impl DefCollector<'_> { | |||
534 | let name = variant_data.name.clone(); | 534 | let name = variant_data.name.clone(); |
535 | let variant = EnumVariantId { parent: e, local_id }; | 535 | let variant = EnumVariantId { parent: e, local_id }; |
536 | let res = PerNs::both(variant.into(), variant.into(), vis); | 536 | let res = PerNs::both(variant.into(), variant.into(), vis); |
537 | (name, res) | 537 | (Some(name), res) |
538 | }) | 538 | }) |
539 | .collect::<Vec<_>>(); | 539 | .collect::<Vec<_>>(); |
540 | self.update(module_id, &resolutions, vis, ImportType::Glob); | 540 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
@@ -550,15 +550,15 @@ impl DefCollector<'_> { | |||
550 | match import.path.segments.last() { | 550 | match import.path.segments.last() { |
551 | Some(last_segment) => { | 551 | Some(last_segment) => { |
552 | let name = match &import.alias { | 552 | let name = match &import.alias { |
553 | Some(ImportAlias::Alias(name)) => name.clone(), | 553 | Some(ImportAlias::Alias(name)) => Some(name.clone()), |
554 | Some(ImportAlias::Underscore) => last_segment.clone(), // FIXME rust-analyzer#2736 | 554 | Some(ImportAlias::Underscore) => None, |
555 | None => last_segment.clone(), | 555 | None => Some(last_segment.clone()), |
556 | }; | 556 | }; |
557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | 557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
558 | 558 | ||
559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | 559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 |
560 | if import.is_extern_crate && module_id == self.def_map.root { | 560 | if import.is_extern_crate && module_id == self.def_map.root { |
561 | if let Some(def) = def.take_types() { | 561 | if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) { |
562 | self.def_map.extern_prelude.insert(name.clone(), def); | 562 | self.def_map.extern_prelude.insert(name.clone(), def); |
563 | } | 563 | } |
564 | } | 564 | } |
@@ -573,7 +573,7 @@ impl DefCollector<'_> { | |||
573 | fn update( | 573 | fn update( |
574 | &mut self, | 574 | &mut self, |
575 | module_id: LocalModuleId, | 575 | module_id: LocalModuleId, |
576 | resolutions: &[(Name, PerNs)], | 576 | resolutions: &[(Option<Name>, PerNs)], |
577 | vis: Visibility, | 577 | vis: Visibility, |
578 | import_type: ImportType, | 578 | import_type: ImportType, |
579 | ) { | 579 | ) { |
@@ -584,7 +584,7 @@ impl DefCollector<'_> { | |||
584 | fn update_recursive( | 584 | fn update_recursive( |
585 | &mut self, | 585 | &mut self, |
586 | module_id: LocalModuleId, | 586 | module_id: LocalModuleId, |
587 | resolutions: &[(Name, PerNs)], | 587 | resolutions: &[(Option<Name>, PerNs)], |
588 | // All resolutions are imported with this visibility; the visibilies in | 588 | // All resolutions are imported with this visibility; the visibilies in |
589 | // the `PerNs` values are ignored and overwritten | 589 | // the `PerNs` values are ignored and overwritten |
590 | vis: Visibility, | 590 | vis: Visibility, |
@@ -595,15 +595,51 @@ impl DefCollector<'_> { | |||
595 | // prevent stack overflows (but this shouldn't be possible) | 595 | // prevent stack overflows (but this shouldn't be possible) |
596 | panic!("infinite recursion in glob imports!"); | 596 | panic!("infinite recursion in glob imports!"); |
597 | } | 597 | } |
598 | let scope = &mut self.def_map.modules[module_id].scope; | ||
599 | let mut changed = false; | 598 | let mut changed = false; |
599 | |||
600 | for (name, res) in resolutions { | 600 | for (name, res) in resolutions { |
601 | changed |= scope.push_res_with_import( | 601 | match name { |
602 | &mut self.from_glob_import, | 602 | Some(name) => { |
603 | (module_id, name.clone()), | 603 | let scope = &mut self.def_map.modules[module_id].scope; |
604 | res.with_visibility(vis), | 604 | changed |= scope.push_res_with_import( |
605 | import_type, | 605 | &mut self.from_glob_import, |
606 | ); | 606 | (module_id, name.clone()), |
607 | res.with_visibility(vis), | ||
608 | import_type, | ||
609 | ); | ||
610 | } | ||
611 | None => { | ||
612 | let tr = match res.take_types() { | ||
613 | Some(ModuleDefId::TraitId(tr)) => tr, | ||
614 | Some(other) => { | ||
615 | log::debug!("non-trait `_` import of {:?}", other); | ||
616 | continue; | ||
617 | } | ||
618 | None => continue, | ||
619 | }; | ||
620 | let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr); | ||
621 | let should_update = match old_vis { | ||
622 | None => true, | ||
623 | Some(old_vis) => { | ||
624 | let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| { | ||
625 | panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr); | ||
626 | }); | ||
627 | |||
628 | if max_vis == old_vis { | ||
629 | false | ||
630 | } else { | ||
631 | mark::hit!(upgrade_underscore_visibility); | ||
632 | true | ||
633 | } | ||
634 | } | ||
635 | }; | ||
636 | |||
637 | if should_update { | ||
638 | changed = true; | ||
639 | self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis); | ||
640 | } | ||
641 | } | ||
642 | } | ||
607 | } | 643 | } |
608 | 644 | ||
609 | if !changed { | 645 | if !changed { |
@@ -950,7 +986,7 @@ impl ModCollector<'_, '_> { | |||
950 | .unwrap_or(Visibility::Public); | 986 | .unwrap_or(Visibility::Public); |
951 | self.def_collector.update( | 987 | self.def_collector.update( |
952 | self.module_id, | 988 | self.module_id, |
953 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 989 | &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], |
954 | vis, | 990 | vis, |
955 | ImportType::Named, | 991 | ImportType::Named, |
956 | ) | 992 | ) |
@@ -1057,7 +1093,7 @@ impl ModCollector<'_, '_> { | |||
1057 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1093 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1058 | self.def_collector.update( | 1094 | self.def_collector.update( |
1059 | self.module_id, | 1095 | self.module_id, |
1060 | &[(name, PerNs::from_def(def, vis, false))], | 1096 | &[(Some(name), PerNs::from_def(def, vis, false))], |
1061 | vis, | 1097 | vis, |
1062 | ImportType::Named, | 1098 | ImportType::Named, |
1063 | ); | 1099 | ); |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 205d3528b..839b1de57 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -558,3 +558,133 @@ mod b { | |||
558 | "#]], | 558 | "#]], |
559 | ); | 559 | ); |
560 | } | 560 | } |
561 | |||
562 | #[test] | ||
563 | fn underscore_import() { | ||
564 | check( | ||
565 | r#" | ||
566 | //- /main.rs | ||
567 | use tr::Tr as _; | ||
568 | use tr::Tr2 as _; | ||
569 | |||
570 | mod tr { | ||
571 | pub trait Tr {} | ||
572 | pub trait Tr2 {} | ||
573 | } | ||
574 | "#, | ||
575 | expect![[r#" | ||
576 | crate | ||
577 | _: t | ||
578 | _: t | ||
579 | tr: t | ||
580 | |||
581 | crate::tr | ||
582 | Tr: t | ||
583 | Tr2: t | ||
584 | "#]], | ||
585 | ); | ||
586 | } | ||
587 | |||
588 | #[test] | ||
589 | fn underscore_reexport() { | ||
590 | check( | ||
591 | r#" | ||
592 | //- /main.rs | ||
593 | mod tr { | ||
594 | pub trait PubTr {} | ||
595 | pub trait PrivTr {} | ||
596 | } | ||
597 | mod reex { | ||
598 | use crate::tr::PrivTr as _; | ||
599 | pub use crate::tr::PubTr as _; | ||
600 | } | ||
601 | use crate::reex::*; | ||
602 | "#, | ||
603 | expect![[r#" | ||
604 | crate | ||
605 | _: t | ||
606 | reex: t | ||
607 | tr: t | ||
608 | |||
609 | crate::tr | ||
610 | PrivTr: t | ||
611 | PubTr: t | ||
612 | |||
613 | crate::reex | ||
614 | _: t | ||
615 | _: t | ||
616 | "#]], | ||
617 | ); | ||
618 | } | ||
619 | |||
620 | #[test] | ||
621 | fn underscore_pub_crate_reexport() { | ||
622 | mark::check!(upgrade_underscore_visibility); | ||
623 | check( | ||
624 | r#" | ||
625 | //- /main.rs crate:main deps:lib | ||
626 | use lib::*; | ||
627 | |||
628 | //- /lib.rs crate:lib | ||
629 | use tr::Tr as _; | ||
630 | pub use tr::Tr as _; | ||
631 | |||
632 | mod tr { | ||
633 | pub trait Tr {} | ||
634 | } | ||
635 | "#, | ||
636 | expect![[r#" | ||
637 | crate | ||
638 | _: t | ||
639 | "#]], | ||
640 | ); | ||
641 | } | ||
642 | |||
643 | #[test] | ||
644 | fn underscore_nontrait() { | ||
645 | check( | ||
646 | r#" | ||
647 | //- /main.rs | ||
648 | mod m { | ||
649 | pub struct Struct; | ||
650 | pub enum Enum {} | ||
651 | pub const CONST: () = (); | ||
652 | } | ||
653 | use crate::m::{Struct as _, Enum as _, CONST as _}; | ||
654 | "#, | ||
655 | expect![[r#" | ||
656 | crate | ||
657 | m: t | ||
658 | |||
659 | crate::m | ||
660 | CONST: v | ||
661 | Enum: t | ||
662 | Struct: t v | ||
663 | "#]], | ||
664 | ); | ||
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn underscore_name_conflict() { | ||
669 | check( | ||
670 | r#" | ||
671 | //- /main.rs | ||
672 | struct Tr; | ||
673 | |||
674 | use tr::Tr as _; | ||
675 | |||
676 | mod tr { | ||
677 | pub trait Tr {} | ||
678 | } | ||
679 | "#, | ||
680 | expect![[r#" | ||
681 | crate | ||
682 | _: t | ||
683 | Tr: t v | ||
684 | tr: t | ||
685 | |||
686 | crate::tr | ||
687 | Tr: t | ||
688 | "#]], | ||
689 | ); | ||
690 | } | ||
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs index 8136cb50c..1abffb4c3 100644 --- a/crates/ra_hir_def/src/visibility.rs +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -5,6 +5,7 @@ use ra_syntax::ast; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | nameres::CrateDefMap, | ||
8 | path::{ModPath, PathKind}, | 9 | path::{ModPath, PathKind}, |
9 | ModuleId, | 10 | ModuleId, |
10 | }; | 11 | }; |
@@ -115,7 +116,7 @@ impl Visibility { | |||
115 | 116 | ||
116 | pub(crate) fn is_visible_from_def_map( | 117 | pub(crate) fn is_visible_from_def_map( |
117 | self, | 118 | self, |
118 | def_map: &crate::nameres::CrateDefMap, | 119 | def_map: &CrateDefMap, |
119 | from_module: crate::LocalModuleId, | 120 | from_module: crate::LocalModuleId, |
120 | ) -> bool { | 121 | ) -> bool { |
121 | let to_module = match self { | 122 | let to_module = match self { |
@@ -129,4 +130,42 @@ impl Visibility { | |||
129 | }); | 130 | }); |
130 | ancestors.any(|m| m == to_module.local_id) | 131 | ancestors.any(|m| m == to_module.local_id) |
131 | } | 132 | } |
133 | |||
134 | /// Returns the most permissive visibility of `self` and `other`. | ||
135 | /// | ||
136 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only | ||
137 | /// visible in unrelated modules). | ||
138 | pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { | ||
139 | match (self, other) { | ||
140 | (Visibility::Module(_), Visibility::Public) | ||
141 | | (Visibility::Public, Visibility::Module(_)) | ||
142 | | (Visibility::Public, Visibility::Public) => Some(Visibility::Public), | ||
143 | (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { | ||
144 | if mod_a.krate != mod_b.krate { | ||
145 | return None; | ||
146 | } | ||
147 | |||
148 | let mut a_ancestors = std::iter::successors(Some(mod_a.local_id), |m| { | ||
149 | let parent_id = def_map[*m].parent?; | ||
150 | Some(parent_id) | ||
151 | }); | ||
152 | let mut b_ancestors = std::iter::successors(Some(mod_b.local_id), |m| { | ||
153 | let parent_id = def_map[*m].parent?; | ||
154 | Some(parent_id) | ||
155 | }); | ||
156 | |||
157 | if a_ancestors.any(|m| m == mod_b.local_id) { | ||
158 | // B is above A | ||
159 | return Some(Visibility::Module(mod_b)); | ||
160 | } | ||
161 | |||
162 | if b_ancestors.any(|m| m == mod_a.local_id) { | ||
163 | // A is above B | ||
164 | return Some(Visibility::Module(mod_a)); | ||
165 | } | ||
166 | |||
167 | None | ||
168 | } | ||
169 | } | ||
170 | } | ||
132 | } | 171 | } |
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index bf30d7151..e0ad1567f 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -6,7 +6,7 @@ use mbe::{ExpandResult, MacroRules}; | |||
6 | use ra_db::{salsa, SourceDatabase}; | 6 | use ra_db::{salsa, SourceDatabase}; |
7 | use ra_parser::FragmentKind; | 7 | use ra_parser::FragmentKind; |
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
9 | use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode}; | 9 | use ra_syntax::{algo::diff, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, | 12 | ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, |
@@ -72,6 +72,8 @@ pub trait AstDatabase: SourceDatabase { | |||
72 | 72 | ||
73 | #[salsa::interned] | 73 | #[salsa::interned] |
74 | fn intern_macro(&self, macro_call: MacroCallLoc) -> LazyMacroId; | 74 | fn intern_macro(&self, macro_call: MacroCallLoc) -> LazyMacroId; |
75 | fn macro_arg_text(&self, id: MacroCallId) -> Option<GreenNode>; | ||
76 | #[salsa::transparent] | ||
75 | fn macro_arg(&self, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>>; | 77 | fn macro_arg(&self, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>>; |
76 | fn macro_def(&self, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>>; | 78 | fn macro_def(&self, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>>; |
77 | fn parse_macro(&self, macro_file: MacroFile) | 79 | fn parse_macro(&self, macro_file: MacroFile) |
@@ -148,10 +150,7 @@ pub(crate) fn macro_def( | |||
148 | } | 150 | } |
149 | } | 151 | } |
150 | 152 | ||
151 | pub(crate) fn macro_arg( | 153 | pub(crate) fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { |
152 | db: &dyn AstDatabase, | ||
153 | id: MacroCallId, | ||
154 | ) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | ||
155 | let id = match id { | 154 | let id = match id { |
156 | MacroCallId::LazyMacro(id) => id, | 155 | MacroCallId::LazyMacro(id) => id, |
157 | MacroCallId::EagerMacro(_id) => { | 156 | MacroCallId::EagerMacro(_id) => { |
@@ -161,7 +160,15 @@ pub(crate) fn macro_arg( | |||
161 | }; | 160 | }; |
162 | let loc = db.lookup_intern_macro(id); | 161 | let loc = db.lookup_intern_macro(id); |
163 | let arg = loc.kind.arg(db)?; | 162 | let arg = loc.kind.arg(db)?; |
164 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&arg)?; | 163 | Some(arg.green().clone()) |
164 | } | ||
165 | |||
166 | pub(crate) fn macro_arg( | ||
167 | db: &dyn AstDatabase, | ||
168 | id: MacroCallId, | ||
169 | ) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | ||
170 | let arg = db.macro_arg_text(id)?; | ||
171 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?; | ||
165 | Some(Arc::new((tt, tmap))) | 172 | Some(Arc::new((tt, tmap))) |
166 | } | 173 | } |
167 | 174 | ||
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 1cf6c1ba9..d9e31ac20 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -262,14 +262,14 @@ pub enum MacroCallKind { | |||
262 | } | 262 | } |
263 | 263 | ||
264 | impl MacroCallKind { | 264 | impl MacroCallKind { |
265 | pub fn file_id(&self) -> HirFileId { | 265 | fn file_id(&self) -> HirFileId { |
266 | match self { | 266 | match self { |
267 | MacroCallKind::FnLike(ast_id) => ast_id.file_id, | 267 | MacroCallKind::FnLike(ast_id) => ast_id.file_id, |
268 | MacroCallKind::Attr(ast_id, _) => ast_id.file_id, | 268 | MacroCallKind::Attr(ast_id, _) => ast_id.file_id, |
269 | } | 269 | } |
270 | } | 270 | } |
271 | 271 | ||
272 | pub fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { | 272 | fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { |
273 | match self { | 273 | match self { |
274 | MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), | 274 | MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), |
275 | MacroCallKind::Attr(ast_id, _) => { | 275 | MacroCallKind::Attr(ast_id, _) => { |
@@ -278,7 +278,7 @@ impl MacroCallKind { | |||
278 | } | 278 | } |
279 | } | 279 | } |
280 | 280 | ||
281 | pub fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { | 281 | fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { |
282 | match self { | 282 | match self { |
283 | MacroCallKind::FnLike(ast_id) => { | 283 | MacroCallKind::FnLike(ast_id) => { |
284 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) | 284 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 78f5e55bb..cdabb359f 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -28,12 +28,11 @@ test_utils = { path = "../test_utils" } | |||
28 | 28 | ||
29 | scoped-tls = "1" | 29 | scoped-tls = "1" |
30 | 30 | ||
31 | chalk-solve = { version = "0.17.0" } | 31 | chalk-solve = { version = "0.18.0" } |
32 | chalk-ir = { version = "0.17.0" } | 32 | chalk-ir = { version = "0.18.0" } |
33 | chalk-recursive = { version = "0.17.0" } | 33 | chalk-recursive = { version = "0.18.0" } |
34 | 34 | ||
35 | [dev-dependencies] | 35 | [dev-dependencies] |
36 | insta = "0.16.0" | ||
37 | expect = { path = "../expect" } | 36 | expect = { path = "../expect" } |
38 | 37 | ||
39 | tracing = "0.1" | 38 | tracing = "0.1" |
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index 758d5f5ac..19770e609 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs | |||
@@ -257,7 +257,12 @@ impl HirDisplay for ApplicationTy { | |||
257 | write!(f, ")")?; | 257 | write!(f, ")")?; |
258 | let ret = sig.ret(); | 258 | let ret = sig.ret(); |
259 | if *ret != Ty::unit() { | 259 | if *ret != Ty::unit() { |
260 | write!(f, " -> {}", ret.display(f.db))?; | 260 | let ret_display = if f.omit_verbose_types() { |
261 | ret.display_truncated(f.db, f.max_size) | ||
262 | } else { | ||
263 | ret.display(f.db) | ||
264 | }; | ||
265 | write!(f, " -> {}", ret_display)?; | ||
261 | } | 266 | } |
262 | } | 267 | } |
263 | TypeCtor::FnDef(def) => { | 268 | TypeCtor::FnDef(def) => { |
@@ -288,7 +293,12 @@ impl HirDisplay for ApplicationTy { | |||
288 | write!(f, ")")?; | 293 | write!(f, ")")?; |
289 | let ret = sig.ret(); | 294 | let ret = sig.ret(); |
290 | if *ret != Ty::unit() { | 295 | if *ret != Ty::unit() { |
291 | write!(f, " -> {}", ret.display(f.db))?; | 296 | let ret_display = if f.omit_verbose_types() { |
297 | ret.display_truncated(f.db, f.max_size) | ||
298 | } else { | ||
299 | ret.display(f.db) | ||
300 | }; | ||
301 | write!(f, " -> {}", ret_display)?; | ||
292 | } | 302 | } |
293 | } | 303 | } |
294 | TypeCtor::Adt(def_id) => { | 304 | TypeCtor::Adt(def_id) => { |
@@ -397,7 +407,13 @@ impl HirDisplay for ApplicationTy { | |||
397 | f.write_joined(sig.params(), ", ")?; | 407 | f.write_joined(sig.params(), ", ")?; |
398 | write!(f, "|")?; | 408 | write!(f, "|")?; |
399 | }; | 409 | }; |
400 | write!(f, " -> {}", sig.ret().display(f.db))?; | 410 | |
411 | let ret_display = if f.omit_verbose_types() { | ||
412 | sig.ret().display_truncated(f.db, f.max_size) | ||
413 | } else { | ||
414 | sig.ret().display(f.db) | ||
415 | }; | ||
416 | write!(f, " -> {}", ret_display)?; | ||
401 | } else { | 417 | } else { |
402 | write!(f, "{{closure}}")?; | 418 | write!(f, "{{closure}}")?; |
403 | } | 419 | } |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 59a21092e..45bc14c37 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -34,8 +34,8 @@ use crate::{ | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | // These tests compare the inference results for all expressions in a file | 36 | // These tests compare the inference results for all expressions in a file |
37 | // against snapshots of the expected results using insta. Use cargo-insta to | 37 | // against snapshots of the expected results using expect. Use |
38 | // update the snapshots. | 38 | // `env UPDATE_EXPECT=1 cargo test -p ra_hir_ty` to update the snapshots. |
39 | 39 | ||
40 | fn setup_tracing() -> tracing::subscriber::DefaultGuard { | 40 | fn setup_tracing() -> tracing::subscriber::DefaultGuard { |
41 | use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; | 41 | use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 45c4e309e..24c53eb02 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | use std::fs; | 1 | use std::fs; |
2 | 2 | ||
3 | use insta::assert_snapshot; | 3 | use expect::expect; |
4 | use test_utils::project_dir; | 4 | use test_utils::project_dir; |
5 | 5 | ||
6 | use super::{check_types, infer}; | 6 | use super::{check_infer, check_types}; |
7 | 7 | ||
8 | #[test] | 8 | #[test] |
9 | fn cfg_impl_def() { | 9 | fn cfg_impl_def() { |
@@ -46,204 +46,204 @@ impl S { | |||
46 | 46 | ||
47 | #[test] | 47 | #[test] |
48 | fn infer_macros_expanded() { | 48 | fn infer_macros_expanded() { |
49 | assert_snapshot!( | 49 | check_infer( |
50 | infer(r#" | 50 | r#" |
51 | struct Foo(Vec<i32>); | 51 | struct Foo(Vec<i32>); |
52 | 52 | ||
53 | macro_rules! foo { | 53 | macro_rules! foo { |
54 | ($($item:expr),*) => { | 54 | ($($item:expr),*) => { |
55 | { | 55 | { |
56 | Foo(vec![$($item,)*]) | 56 | Foo(vec![$($item,)*]) |
57 | } | 57 | } |
58 | }; | 58 | }; |
59 | } | 59 | } |
60 | 60 | ||
61 | fn main() { | 61 | fn main() { |
62 | let x = foo!(1,2); | 62 | let x = foo!(1,2); |
63 | } | 63 | } |
64 | "#), | 64 | "#, |
65 | @r###" | 65 | expect![[r#" |
66 | !0..17 '{Foo(v...,2,])}': Foo | 66 | !0..17 '{Foo(v...,2,])}': Foo |
67 | !1..4 'Foo': Foo({unknown}) -> Foo | 67 | !1..4 'Foo': Foo({unknown}) -> Foo |
68 | !1..16 'Foo(vec![1,2,])': Foo | 68 | !1..16 'Foo(vec![1,2,])': Foo |
69 | !5..15 'vec![1,2,]': {unknown} | 69 | !5..15 'vec![1,2,]': {unknown} |
70 | 155..181 '{ ...,2); }': () | 70 | 155..181 '{ ...,2); }': () |
71 | 165..166 'x': Foo | 71 | 165..166 'x': Foo |
72 | "### | 72 | "#]], |
73 | ); | 73 | ); |
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn infer_legacy_textual_scoped_macros_expanded() { | 77 | fn infer_legacy_textual_scoped_macros_expanded() { |
78 | assert_snapshot!( | 78 | check_infer( |
79 | infer(r#" | 79 | r#" |
80 | struct Foo(Vec<i32>); | 80 | struct Foo(Vec<i32>); |
81 | 81 | ||
82 | #[macro_use] | 82 | #[macro_use] |
83 | mod m { | 83 | mod m { |
84 | macro_rules! foo { | 84 | macro_rules! foo { |
85 | ($($item:expr),*) => { | 85 | ($($item:expr),*) => { |
86 | { | 86 | { |
87 | Foo(vec![$($item,)*]) | 87 | Foo(vec![$($item,)*]) |
88 | } | ||
89 | }; | ||
88 | } | 90 | } |
89 | }; | 91 | } |
90 | } | ||
91 | } | ||
92 | 92 | ||
93 | fn main() { | 93 | fn main() { |
94 | let x = foo!(1,2); | 94 | let x = foo!(1,2); |
95 | let y = crate::foo!(1,2); | 95 | let y = crate::foo!(1,2); |
96 | } | 96 | } |
97 | "#), | 97 | "#, |
98 | @r###" | 98 | expect![[r#" |
99 | !0..17 '{Foo(v...,2,])}': Foo | 99 | !0..17 '{Foo(v...,2,])}': Foo |
100 | !1..4 'Foo': Foo({unknown}) -> Foo | 100 | !1..4 'Foo': Foo({unknown}) -> Foo |
101 | !1..16 'Foo(vec![1,2,])': Foo | 101 | !1..16 'Foo(vec![1,2,])': Foo |
102 | !5..15 'vec![1,2,]': {unknown} | 102 | !5..15 'vec![1,2,]': {unknown} |
103 | 194..250 '{ ...,2); }': () | 103 | 194..250 '{ ...,2); }': () |
104 | 204..205 'x': Foo | 104 | 204..205 'x': Foo |
105 | 227..228 'y': {unknown} | 105 | 227..228 'y': {unknown} |
106 | 231..247 'crate:...!(1,2)': {unknown} | 106 | 231..247 'crate:...!(1,2)': {unknown} |
107 | "### | 107 | "#]], |
108 | ); | 108 | ); |
109 | } | 109 | } |
110 | 110 | ||
111 | #[test] | 111 | #[test] |
112 | fn infer_path_qualified_macros_expanded() { | 112 | fn infer_path_qualified_macros_expanded() { |
113 | assert_snapshot!( | 113 | check_infer( |
114 | infer(r#" | 114 | r#" |
115 | #[macro_export] | 115 | #[macro_export] |
116 | macro_rules! foo { | 116 | macro_rules! foo { |
117 | () => { 42i32 } | 117 | () => { 42i32 } |
118 | } | 118 | } |
119 | 119 | ||
120 | mod m { | 120 | mod m { |
121 | pub use super::foo as bar; | 121 | pub use super::foo as bar; |
122 | } | 122 | } |
123 | 123 | ||
124 | fn main() { | 124 | fn main() { |
125 | let x = crate::foo!(); | 125 | let x = crate::foo!(); |
126 | let y = m::bar!(); | 126 | let y = m::bar!(); |
127 | } | 127 | } |
128 | "#), | 128 | "#, |
129 | @r###" | 129 | expect![[r#" |
130 | !0..5 '42i32': i32 | 130 | !0..5 '42i32': i32 |
131 | !0..5 '42i32': i32 | 131 | !0..5 '42i32': i32 |
132 | 110..163 '{ ...!(); }': () | 132 | 110..163 '{ ...!(); }': () |
133 | 120..121 'x': i32 | 133 | 120..121 'x': i32 |
134 | 147..148 'y': i32 | 134 | 147..148 'y': i32 |
135 | "### | 135 | "#]], |
136 | ); | 136 | ); |
137 | } | 137 | } |
138 | 138 | ||
139 | #[test] | 139 | #[test] |
140 | fn expr_macro_expanded_in_various_places() { | 140 | fn expr_macro_expanded_in_various_places() { |
141 | assert_snapshot!( | 141 | check_infer( |
142 | infer(r#" | 142 | r#" |
143 | macro_rules! spam { | 143 | macro_rules! spam { |
144 | () => (1isize); | 144 | () => (1isize); |
145 | } | 145 | } |
146 | 146 | ||
147 | fn spam() { | 147 | fn spam() { |
148 | spam!(); | 148 | spam!(); |
149 | (spam!()); | 149 | (spam!()); |
150 | spam!().spam(spam!()); | 150 | spam!().spam(spam!()); |
151 | for _ in spam!() {} | 151 | for _ in spam!() {} |
152 | || spam!(); | 152 | || spam!(); |
153 | while spam!() {} | 153 | while spam!() {} |
154 | break spam!(); | 154 | break spam!(); |
155 | return spam!(); | 155 | return spam!(); |
156 | match spam!() { | 156 | match spam!() { |
157 | _ if spam!() => spam!(), | 157 | _ if spam!() => spam!(), |
158 | } | 158 | } |
159 | spam!()(spam!()); | 159 | spam!()(spam!()); |
160 | Spam { spam: spam!() }; | 160 | Spam { spam: spam!() }; |
161 | spam!()[spam!()]; | 161 | spam!()[spam!()]; |
162 | await spam!(); | 162 | await spam!(); |
163 | spam!() as usize; | 163 | spam!() as usize; |
164 | &spam!(); | 164 | &spam!(); |
165 | -spam!(); | 165 | -spam!(); |
166 | spam!()..spam!(); | 166 | spam!()..spam!(); |
167 | spam!() + spam!(); | 167 | spam!() + spam!(); |
168 | } | 168 | } |
169 | "#), | 169 | "#, |
170 | @r###" | 170 | expect![[r#" |
171 | !0..6 '1isize': isize | 171 | !0..6 '1isize': isize |
172 | !0..6 '1isize': isize | 172 | !0..6 '1isize': isize |
173 | !0..6 '1isize': isize | 173 | !0..6 '1isize': isize |
174 | !0..6 '1isize': isize | 174 | !0..6 '1isize': isize |
175 | !0..6 '1isize': isize | 175 | !0..6 '1isize': isize |
176 | !0..6 '1isize': isize | 176 | !0..6 '1isize': isize |
177 | !0..6 '1isize': isize | 177 | !0..6 '1isize': isize |
178 | !0..6 '1isize': isize | 178 | !0..6 '1isize': isize |
179 | !0..6 '1isize': isize | 179 | !0..6 '1isize': isize |
180 | !0..6 '1isize': isize | 180 | !0..6 '1isize': isize |
181 | !0..6 '1isize': isize | 181 | !0..6 '1isize': isize |
182 | !0..6 '1isize': isize | 182 | !0..6 '1isize': isize |
183 | !0..6 '1isize': isize | 183 | !0..6 '1isize': isize |
184 | !0..6 '1isize': isize | 184 | !0..6 '1isize': isize |
185 | !0..6 '1isize': isize | 185 | !0..6 '1isize': isize |
186 | !0..6 '1isize': isize | 186 | !0..6 '1isize': isize |
187 | !0..6 '1isize': isize | 187 | !0..6 '1isize': isize |
188 | !0..6 '1isize': isize | 188 | !0..6 '1isize': isize |
189 | !0..6 '1isize': isize | 189 | !0..6 '1isize': isize |
190 | !0..6 '1isize': isize | 190 | !0..6 '1isize': isize |
191 | !0..6 '1isize': isize | 191 | !0..6 '1isize': isize |
192 | !0..6 '1isize': isize | 192 | !0..6 '1isize': isize |
193 | !0..6 '1isize': isize | 193 | !0..6 '1isize': isize |
194 | !0..6 '1isize': isize | 194 | !0..6 '1isize': isize |
195 | !0..6 '1isize': isize | 195 | !0..6 '1isize': isize |
196 | 53..456 '{ ...!(); }': () | 196 | 53..456 '{ ...!(); }': () |
197 | 87..108 'spam!(...am!())': {unknown} | 197 | 87..108 'spam!(...am!())': {unknown} |
198 | 114..133 'for _ ...!() {}': () | 198 | 114..133 'for _ ...!() {}': () |
199 | 118..119 '_': {unknown} | 199 | 118..119 '_': {unknown} |
200 | 131..133 '{}': () | 200 | 131..133 '{}': () |
201 | 138..148 '|| spam!()': || -> isize | 201 | 138..148 '|| spam!()': || -> isize |
202 | 154..170 'while ...!() {}': () | 202 | 154..170 'while ...!() {}': () |
203 | 168..170 '{}': () | 203 | 168..170 '{}': () |
204 | 175..188 'break spam!()': ! | 204 | 175..188 'break spam!()': ! |
205 | 194..208 'return spam!()': ! | 205 | 194..208 'return spam!()': ! |
206 | 214..268 'match ... }': isize | 206 | 214..268 'match ... }': isize |
207 | 238..239 '_': isize | 207 | 238..239 '_': isize |
208 | 273..289 'spam!(...am!())': {unknown} | 208 | 273..289 'spam!(...am!())': {unknown} |
209 | 295..317 'Spam {...m!() }': {unknown} | 209 | 295..317 'Spam {...m!() }': {unknown} |
210 | 323..339 'spam!(...am!()]': {unknown} | 210 | 323..339 'spam!(...am!()]': {unknown} |
211 | 364..380 'spam!(... usize': usize | 211 | 364..380 'spam!(... usize': usize |
212 | 386..394 '&spam!()': &isize | 212 | 386..394 '&spam!()': &isize |
213 | 400..408 '-spam!()': isize | 213 | 400..408 '-spam!()': isize |
214 | 414..430 'spam!(...pam!()': {unknown} | 214 | 414..430 'spam!(...pam!()': {unknown} |
215 | 436..453 'spam!(...pam!()': isize | 215 | 436..453 'spam!(...pam!()': isize |
216 | "### | 216 | "#]], |
217 | ); | 217 | ); |
218 | } | 218 | } |
219 | 219 | ||
220 | #[test] | 220 | #[test] |
221 | fn infer_type_value_macro_having_same_name() { | 221 | fn infer_type_value_macro_having_same_name() { |
222 | assert_snapshot!( | 222 | check_infer( |
223 | infer(r#" | 223 | r#" |
224 | #[macro_export] | 224 | #[macro_export] |
225 | macro_rules! foo { | 225 | macro_rules! foo { |
226 | () => { | 226 | () => { |
227 | mod foo { | 227 | mod foo { |
228 | pub use super::foo; | 228 | pub use super::foo; |
229 | } | ||
230 | }; | ||
231 | ($x:tt) => { | ||
232 | $x | ||
233 | }; | ||
229 | } | 234 | } |
230 | }; | ||
231 | ($x:tt) => { | ||
232 | $x | ||
233 | }; | ||
234 | } | ||
235 | 235 | ||
236 | foo!(); | 236 | foo!(); |
237 | 237 | ||
238 | fn foo() { | 238 | fn foo() { |
239 | let foo = foo::foo!(42i32); | 239 | let foo = foo::foo!(42i32); |
240 | } | 240 | } |
241 | "#), | 241 | "#, |
242 | @r###" | 242 | expect![[r#" |
243 | !0..5 '42i32': i32 | 243 | !0..5 '42i32': i32 |
244 | 170..205 '{ ...32); }': () | 244 | 170..205 '{ ...32); }': () |
245 | 180..183 'foo': i32 | 245 | 180..183 'foo': i32 |
246 | "### | 246 | "#]], |
247 | ); | 247 | ); |
248 | } | 248 | } |
249 | 249 | ||
@@ -372,50 +372,50 @@ expand!(); | |||
372 | 372 | ||
373 | #[test] | 373 | #[test] |
374 | fn infer_type_value_non_legacy_macro_use_as() { | 374 | fn infer_type_value_non_legacy_macro_use_as() { |
375 | assert_snapshot!( | 375 | check_infer( |
376 | infer(r#" | 376 | r#" |
377 | mod m { | 377 | mod m { |
378 | macro_rules! _foo { | 378 | macro_rules! _foo { |
379 | ($x:ident) => { type $x = u64; } | 379 | ($x:ident) => { type $x = u64; } |
380 | } | 380 | } |
381 | pub(crate) use _foo as foo; | 381 | pub(crate) use _foo as foo; |
382 | } | 382 | } |
383 | 383 | ||
384 | m::foo!(foo); | 384 | m::foo!(foo); |
385 | use foo as bar; | 385 | use foo as bar; |
386 | fn f() -> bar { 0 } | 386 | fn f() -> bar { 0 } |
387 | fn main() { | 387 | fn main() { |
388 | let _a = f(); | 388 | let _a = f(); |
389 | } | 389 | } |
390 | "#), | 390 | "#, |
391 | @r###" | 391 | expect![[r#" |
392 | 158..163 '{ 0 }': u64 | 392 | 158..163 '{ 0 }': u64 |
393 | 160..161 '0': u64 | 393 | 160..161 '0': u64 |
394 | 174..196 '{ ...f(); }': () | 394 | 174..196 '{ ...f(); }': () |
395 | 184..186 '_a': u64 | 395 | 184..186 '_a': u64 |
396 | 190..191 'f': fn f() -> u64 | 396 | 190..191 'f': fn f() -> u64 |
397 | 190..193 'f()': u64 | 397 | 190..193 'f()': u64 |
398 | "### | 398 | "#]], |
399 | ); | 399 | ); |
400 | } | 400 | } |
401 | 401 | ||
402 | #[test] | 402 | #[test] |
403 | fn infer_local_macro() { | 403 | fn infer_local_macro() { |
404 | assert_snapshot!( | 404 | check_infer( |
405 | infer(r#" | 405 | r#" |
406 | fn main() { | 406 | fn main() { |
407 | macro_rules! foo { | 407 | macro_rules! foo { |
408 | () => { 1usize } | 408 | () => { 1usize } |
409 | } | 409 | } |
410 | let _a = foo!(); | 410 | let _a = foo!(); |
411 | } | 411 | } |
412 | "#), | 412 | "#, |
413 | @r###" | 413 | expect![[r#" |
414 | !0..6 '1usize': usize | 414 | !0..6 '1usize': usize |
415 | 10..89 '{ ...!(); }': () | 415 | 10..89 '{ ...!(); }': () |
416 | 16..65 'macro_... }': {unknown} | 416 | 16..65 'macro_... }': {unknown} |
417 | 74..76 '_a': usize | 417 | 74..76 '_a': usize |
418 | "### | 418 | "#]], |
419 | ); | 419 | ); |
420 | } | 420 | } |
421 | 421 | ||
@@ -446,77 +446,77 @@ macro_rules! bar { | |||
446 | 446 | ||
447 | #[test] | 447 | #[test] |
448 | fn infer_builtin_macros_line() { | 448 | fn infer_builtin_macros_line() { |
449 | assert_snapshot!( | 449 | check_infer( |
450 | infer(r#" | 450 | r#" |
451 | #[rustc_builtin_macro] | 451 | #[rustc_builtin_macro] |
452 | macro_rules! line {() => {}} | 452 | macro_rules! line {() => {}} |
453 | 453 | ||
454 | fn main() { | 454 | fn main() { |
455 | let x = line!(); | 455 | let x = line!(); |
456 | } | 456 | } |
457 | "#), | 457 | "#, |
458 | @r###" | 458 | expect![[r#" |
459 | !0..1 '0': i32 | 459 | !0..1 '0': i32 |
460 | 63..87 '{ ...!(); }': () | 460 | 63..87 '{ ...!(); }': () |
461 | 73..74 'x': i32 | 461 | 73..74 'x': i32 |
462 | "### | 462 | "#]], |
463 | ); | 463 | ); |
464 | } | 464 | } |
465 | 465 | ||
466 | #[test] | 466 | #[test] |
467 | fn infer_builtin_macros_file() { | 467 | fn infer_builtin_macros_file() { |
468 | assert_snapshot!( | 468 | check_infer( |
469 | infer(r#" | 469 | r#" |
470 | #[rustc_builtin_macro] | 470 | #[rustc_builtin_macro] |
471 | macro_rules! file {() => {}} | 471 | macro_rules! file {() => {}} |
472 | 472 | ||
473 | fn main() { | 473 | fn main() { |
474 | let x = file!(); | 474 | let x = file!(); |
475 | } | 475 | } |
476 | "#), | 476 | "#, |
477 | @r###" | 477 | expect![[r#" |
478 | !0..2 '""': &str | 478 | !0..2 '""': &str |
479 | 63..87 '{ ...!(); }': () | 479 | 63..87 '{ ...!(); }': () |
480 | 73..74 'x': &str | 480 | 73..74 'x': &str |
481 | "### | 481 | "#]], |
482 | ); | 482 | ); |
483 | } | 483 | } |
484 | 484 | ||
485 | #[test] | 485 | #[test] |
486 | fn infer_builtin_macros_column() { | 486 | fn infer_builtin_macros_column() { |
487 | assert_snapshot!( | 487 | check_infer( |
488 | infer(r#" | 488 | r#" |
489 | #[rustc_builtin_macro] | 489 | #[rustc_builtin_macro] |
490 | macro_rules! column {() => {}} | 490 | macro_rules! column {() => {}} |
491 | 491 | ||
492 | fn main() { | 492 | fn main() { |
493 | let x = column!(); | 493 | let x = column!(); |
494 | } | 494 | } |
495 | "#), | 495 | "#, |
496 | @r###" | 496 | expect![[r#" |
497 | !0..1 '0': i32 | 497 | !0..1 '0': i32 |
498 | 65..91 '{ ...!(); }': () | 498 | 65..91 '{ ...!(); }': () |
499 | 75..76 'x': i32 | 499 | 75..76 'x': i32 |
500 | "### | 500 | "#]], |
501 | ); | 501 | ); |
502 | } | 502 | } |
503 | 503 | ||
504 | #[test] | 504 | #[test] |
505 | fn infer_builtin_macros_concat() { | 505 | fn infer_builtin_macros_concat() { |
506 | assert_snapshot!( | 506 | check_infer( |
507 | infer(r#" | 507 | r#" |
508 | #[rustc_builtin_macro] | 508 | #[rustc_builtin_macro] |
509 | macro_rules! concat {() => {}} | 509 | macro_rules! concat {() => {}} |
510 | 510 | ||
511 | fn main() { | 511 | fn main() { |
512 | let x = concat!("hello", concat!("world", "!")); | 512 | let x = concat!("hello", concat!("world", "!")); |
513 | } | 513 | } |
514 | "#), | 514 | "#, |
515 | @r###" | 515 | expect![[r#" |
516 | !0..13 '"helloworld!"': &str | 516 | !0..13 '"helloworld!"': &str |
517 | 65..121 '{ ...")); }': () | 517 | 65..121 '{ ...")); }': () |
518 | 75..76 'x': &str | 518 | 75..76 'x': &str |
519 | "### | 519 | "#]], |
520 | ); | 520 | ); |
521 | } | 521 | } |
522 | 522 | ||
@@ -622,7 +622,7 @@ macro_rules! include {() => {}} | |||
622 | include!("main.rs"); | 622 | include!("main.rs"); |
623 | 623 | ||
624 | fn main() { | 624 | fn main() { |
625 | 0 | 625 | 0 |
626 | } //^ i32 | 626 | } //^ i32 |
627 | "#, | 627 | "#, |
628 | ); | 628 | ); |
@@ -630,42 +630,42 @@ fn main() { | |||
630 | 630 | ||
631 | #[test] | 631 | #[test] |
632 | fn infer_builtin_macros_concat_with_lazy() { | 632 | fn infer_builtin_macros_concat_with_lazy() { |
633 | assert_snapshot!( | 633 | check_infer( |
634 | infer(r#" | 634 | r#" |
635 | macro_rules! hello {() => {"hello"}} | 635 | macro_rules! hello {() => {"hello"}} |
636 | 636 | ||
637 | #[rustc_builtin_macro] | 637 | #[rustc_builtin_macro] |
638 | macro_rules! concat {() => {}} | 638 | macro_rules! concat {() => {}} |
639 | 639 | ||
640 | fn main() { | 640 | fn main() { |
641 | let x = concat!(hello!(), concat!("world", "!")); | 641 | let x = concat!(hello!(), concat!("world", "!")); |
642 | } | 642 | } |
643 | "#), | 643 | "#, |
644 | @r###" | 644 | expect![[r#" |
645 | !0..13 '"helloworld!"': &str | 645 | !0..13 '"helloworld!"': &str |
646 | 103..160 '{ ...")); }': () | 646 | 103..160 '{ ...")); }': () |
647 | 113..114 'x': &str | 647 | 113..114 'x': &str |
648 | "### | 648 | "#]], |
649 | ); | 649 | ); |
650 | } | 650 | } |
651 | 651 | ||
652 | #[test] | 652 | #[test] |
653 | fn infer_builtin_macros_env() { | 653 | fn infer_builtin_macros_env() { |
654 | assert_snapshot!( | 654 | check_infer( |
655 | infer(r#" | 655 | r#" |
656 | //- /main.rs env:foo=bar | 656 | //- /main.rs env:foo=bar |
657 | #[rustc_builtin_macro] | 657 | #[rustc_builtin_macro] |
658 | macro_rules! env {() => {}} | 658 | macro_rules! env {() => {}} |
659 | 659 | ||
660 | fn main() { | 660 | fn main() { |
661 | let x = env!("foo"); | 661 | let x = env!("foo"); |
662 | } | 662 | } |
663 | "#), | 663 | "#, |
664 | @r###" | 664 | expect![[r#" |
665 | !0..22 '"__RA_...TED__"': &str | 665 | !0..22 '"__RA_...TED__"': &str |
666 | 62..90 '{ ...o"); }': () | 666 | 62..90 '{ ...o"); }': () |
667 | 72..73 'x': &str | 667 | 72..73 'x': &str |
668 | "### | 668 | "#]], |
669 | ); | 669 | ); |
670 | } | 670 | } |
671 | 671 | ||
@@ -763,25 +763,25 @@ fn test() { | |||
763 | 763 | ||
764 | #[test] | 764 | #[test] |
765 | fn macro_in_arm() { | 765 | fn macro_in_arm() { |
766 | assert_snapshot!( | 766 | check_infer( |
767 | infer(r#" | 767 | r#" |
768 | macro_rules! unit { | 768 | macro_rules! unit { |
769 | () => { () }; | 769 | () => { () }; |
770 | } | 770 | } |
771 | 771 | ||
772 | fn main() { | 772 | fn main() { |
773 | let x = match () { | 773 | let x = match () { |
774 | unit!() => 92u32, | 774 | unit!() => 92u32, |
775 | }; | 775 | }; |
776 | } | 776 | } |
777 | "#), | 777 | "#, |
778 | @r###" | 778 | expect![[r#" |
779 | 51..110 '{ ... }; }': () | 779 | 51..110 '{ ... }; }': () |
780 | 61..62 'x': u32 | 780 | 61..62 'x': u32 |
781 | 65..107 'match ... }': u32 | 781 | 65..107 'match ... }': u32 |
782 | 71..73 '()': () | 782 | 71..73 '()': () |
783 | 84..91 'unit!()': () | 783 | 84..91 'unit!()': () |
784 | 95..100 '92u32': u32 | 784 | 95..100 '92u32': u32 |
785 | "### | 785 | "#]], |
786 | ); | 786 | ); |
787 | } | 787 | } |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 9c8f22314..fa68355aa 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -1,245 +1,245 @@ | |||
1 | use insta::assert_snapshot; | 1 | use expect::expect; |
2 | 2 | ||
3 | use super::{check_types, infer}; | 3 | use super::{check_infer, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn infer_slice_method() { | 6 | fn infer_slice_method() { |
7 | assert_snapshot!( | 7 | check_infer( |
8 | infer(r#" | 8 | r#" |
9 | #[lang = "slice"] | 9 | #[lang = "slice"] |
10 | impl<T> [T] { | 10 | impl<T> [T] { |
11 | fn foo(&self) -> T { | 11 | fn foo(&self) -> T { |
12 | loop {} | 12 | loop {} |
13 | } | 13 | } |
14 | } | 14 | } |
15 | 15 | ||
16 | #[lang = "slice_alloc"] | 16 | #[lang = "slice_alloc"] |
17 | impl<T> [T] {} | 17 | impl<T> [T] {} |
18 | 18 | ||
19 | fn test(x: &[u8]) { | 19 | fn test(x: &[u8]) { |
20 | <[_]>::foo(x); | 20 | <[_]>::foo(x); |
21 | } | 21 | } |
22 | "#), | 22 | "#, |
23 | @r###" | 23 | expect![[r#" |
24 | 44..48 'self': &[T] | 24 | 44..48 'self': &[T] |
25 | 55..78 '{ ... }': T | 25 | 55..78 '{ ... }': T |
26 | 65..72 'loop {}': ! | 26 | 65..72 'loop {}': ! |
27 | 70..72 '{}': () | 27 | 70..72 '{}': () |
28 | 130..131 'x': &[u8] | 28 | 130..131 'x': &[u8] |
29 | 140..162 '{ ...(x); }': () | 29 | 140..162 '{ ...(x); }': () |
30 | 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 | 30 | 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 |
31 | 146..159 '<[_]>::foo(x)': u8 | 31 | 146..159 '<[_]>::foo(x)': u8 |
32 | 157..158 'x': &[u8] | 32 | 157..158 'x': &[u8] |
33 | "### | 33 | "#]], |
34 | ); | 34 | ); |
35 | } | 35 | } |
36 | 36 | ||
37 | #[test] | 37 | #[test] |
38 | fn infer_associated_method_struct() { | 38 | fn infer_associated_method_struct() { |
39 | assert_snapshot!( | 39 | check_infer( |
40 | infer(r#" | 40 | r#" |
41 | struct A { x: u32 } | 41 | struct A { x: u32 } |
42 | 42 | ||
43 | impl A { | 43 | impl A { |
44 | fn new() -> A { | 44 | fn new() -> A { |
45 | A { x: 0 } | 45 | A { x: 0 } |
46 | } | 46 | } |
47 | } | 47 | } |
48 | fn test() { | 48 | fn test() { |
49 | let a = A::new(); | 49 | let a = A::new(); |
50 | a.x; | 50 | a.x; |
51 | } | 51 | } |
52 | "#), | 52 | "#, |
53 | @r###" | 53 | expect![[r#" |
54 | 48..74 '{ ... }': A | 54 | 48..74 '{ ... }': A |
55 | 58..68 'A { x: 0 }': A | 55 | 58..68 'A { x: 0 }': A |
56 | 65..66 '0': u32 | 56 | 65..66 '0': u32 |
57 | 87..121 '{ ...a.x; }': () | 57 | 87..121 '{ ...a.x; }': () |
58 | 97..98 'a': A | 58 | 97..98 'a': A |
59 | 101..107 'A::new': fn new() -> A | 59 | 101..107 'A::new': fn new() -> A |
60 | 101..109 'A::new()': A | 60 | 101..109 'A::new()': A |
61 | 115..116 'a': A | 61 | 115..116 'a': A |
62 | 115..118 'a.x': u32 | 62 | 115..118 'a.x': u32 |
63 | "### | 63 | "#]], |
64 | ); | 64 | ); |
65 | } | 65 | } |
66 | 66 | ||
67 | #[test] | 67 | #[test] |
68 | fn infer_associated_method_enum() { | 68 | fn infer_associated_method_enum() { |
69 | assert_snapshot!( | 69 | check_infer( |
70 | infer(r#" | 70 | r#" |
71 | enum A { B, C } | 71 | enum A { B, C } |
72 | 72 | ||
73 | impl A { | 73 | impl A { |
74 | pub fn b() -> A { | 74 | pub fn b() -> A { |
75 | A::B | 75 | A::B |
76 | } | 76 | } |
77 | pub fn c() -> A { | 77 | pub fn c() -> A { |
78 | A::C | 78 | A::C |
79 | } | 79 | } |
80 | } | 80 | } |
81 | fn test() { | 81 | fn test() { |
82 | let a = A::b(); | 82 | let a = A::b(); |
83 | a; | 83 | a; |
84 | let c = A::c(); | 84 | let c = A::c(); |
85 | c; | 85 | c; |
86 | } | 86 | } |
87 | "#), | 87 | "#, |
88 | @r###" | 88 | expect![[r#" |
89 | 46..66 '{ ... }': A | 89 | 46..66 '{ ... }': A |
90 | 56..60 'A::B': A | 90 | 56..60 'A::B': A |
91 | 87..107 '{ ... }': A | 91 | 87..107 '{ ... }': A |
92 | 97..101 'A::C': A | 92 | 97..101 'A::C': A |
93 | 120..177 '{ ... c; }': () | 93 | 120..177 '{ ... c; }': () |
94 | 130..131 'a': A | 94 | 130..131 'a': A |
95 | 134..138 'A::b': fn b() -> A | 95 | 134..138 'A::b': fn b() -> A |
96 | 134..140 'A::b()': A | 96 | 134..140 'A::b()': A |
97 | 146..147 'a': A | 97 | 146..147 'a': A |
98 | 157..158 'c': A | 98 | 157..158 'c': A |
99 | 161..165 'A::c': fn c() -> A | 99 | 161..165 'A::c': fn c() -> A |
100 | 161..167 'A::c()': A | 100 | 161..167 'A::c()': A |
101 | 173..174 'c': A | 101 | 173..174 'c': A |
102 | "### | 102 | "#]], |
103 | ); | 103 | ); |
104 | } | 104 | } |
105 | 105 | ||
106 | #[test] | 106 | #[test] |
107 | fn infer_associated_method_with_modules() { | 107 | fn infer_associated_method_with_modules() { |
108 | assert_snapshot!( | 108 | check_infer( |
109 | infer(r#" | 109 | r#" |
110 | mod a { | 110 | mod a { |
111 | struct A; | 111 | struct A; |
112 | impl A { pub fn thing() -> A { A {} }} | 112 | impl A { pub fn thing() -> A { A {} }} |
113 | } | 113 | } |
114 | 114 | ||
115 | mod b { | 115 | mod b { |
116 | struct B; | 116 | struct B; |
117 | impl B { pub fn thing() -> u32 { 99 }} | 117 | impl B { pub fn thing() -> u32 { 99 }} |
118 | 118 | ||
119 | mod c { | 119 | mod c { |
120 | struct C; | 120 | struct C; |
121 | impl C { pub fn thing() -> C { C {} }} | 121 | impl C { pub fn thing() -> C { C {} }} |
122 | } | 122 | } |
123 | } | 123 | } |
124 | use b::c; | 124 | use b::c; |
125 | 125 | ||
126 | fn test() { | 126 | fn test() { |
127 | let x = a::A::thing(); | 127 | let x = a::A::thing(); |
128 | let y = b::B::thing(); | 128 | let y = b::B::thing(); |
129 | let z = c::C::thing(); | 129 | let z = c::C::thing(); |
130 | } | 130 | } |
131 | "#), | 131 | "#, |
132 | @r###" | 132 | expect![[r#" |
133 | 55..63 '{ A {} }': A | 133 | 55..63 '{ A {} }': A |
134 | 57..61 'A {}': A | 134 | 57..61 'A {}': A |
135 | 125..131 '{ 99 }': u32 | 135 | 125..131 '{ 99 }': u32 |
136 | 127..129 '99': u32 | 136 | 127..129 '99': u32 |
137 | 201..209 '{ C {} }': C | 137 | 201..209 '{ C {} }': C |
138 | 203..207 'C {}': C | 138 | 203..207 'C {}': C |
139 | 240..324 '{ ...g(); }': () | 139 | 240..324 '{ ...g(); }': () |
140 | 250..251 'x': A | 140 | 250..251 'x': A |
141 | 254..265 'a::A::thing': fn thing() -> A | 141 | 254..265 'a::A::thing': fn thing() -> A |
142 | 254..267 'a::A::thing()': A | 142 | 254..267 'a::A::thing()': A |
143 | 277..278 'y': u32 | 143 | 277..278 'y': u32 |
144 | 281..292 'b::B::thing': fn thing() -> u32 | 144 | 281..292 'b::B::thing': fn thing() -> u32 |
145 | 281..294 'b::B::thing()': u32 | 145 | 281..294 'b::B::thing()': u32 |
146 | 304..305 'z': C | 146 | 304..305 'z': C |
147 | 308..319 'c::C::thing': fn thing() -> C | 147 | 308..319 'c::C::thing': fn thing() -> C |
148 | 308..321 'c::C::thing()': C | 148 | 308..321 'c::C::thing()': C |
149 | "### | 149 | "#]], |
150 | ); | 150 | ); |
151 | } | 151 | } |
152 | 152 | ||
153 | #[test] | 153 | #[test] |
154 | fn infer_associated_method_generics() { | 154 | fn infer_associated_method_generics() { |
155 | assert_snapshot!( | 155 | check_infer( |
156 | infer(r#" | 156 | r#" |
157 | struct Gen<T> { | 157 | struct Gen<T> { |
158 | val: T | 158 | val: T |
159 | } | 159 | } |
160 | 160 | ||
161 | impl<T> Gen<T> { | 161 | impl<T> Gen<T> { |
162 | pub fn make(val: T) -> Gen<T> { | 162 | pub fn make(val: T) -> Gen<T> { |
163 | Gen { val } | 163 | Gen { val } |
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | fn test() { | 167 | fn test() { |
168 | let a = Gen::make(0u32); | 168 | let a = Gen::make(0u32); |
169 | } | 169 | } |
170 | "#), | 170 | "#, |
171 | @r###" | 171 | expect![[r#" |
172 | 63..66 'val': T | 172 | 63..66 'val': T |
173 | 81..108 '{ ... }': Gen<T> | 173 | 81..108 '{ ... }': Gen<T> |
174 | 91..102 'Gen { val }': Gen<T> | 174 | 91..102 'Gen { val }': Gen<T> |
175 | 97..100 'val': T | 175 | 97..100 'val': T |
176 | 122..154 '{ ...32); }': () | 176 | 122..154 '{ ...32); }': () |
177 | 132..133 'a': Gen<u32> | 177 | 132..133 'a': Gen<u32> |
178 | 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32> | 178 | 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32> |
179 | 136..151 'Gen::make(0u32)': Gen<u32> | 179 | 136..151 'Gen::make(0u32)': Gen<u32> |
180 | 146..150 '0u32': u32 | 180 | 146..150 '0u32': u32 |
181 | "### | 181 | "#]], |
182 | ); | 182 | ); |
183 | } | 183 | } |
184 | 184 | ||
185 | #[test] | 185 | #[test] |
186 | fn infer_associated_method_generics_without_args() { | 186 | fn infer_associated_method_generics_without_args() { |
187 | assert_snapshot!( | 187 | check_infer( |
188 | infer(r#" | 188 | r#" |
189 | struct Gen<T> { | 189 | struct Gen<T> { |
190 | val: T | 190 | val: T |
191 | } | 191 | } |
192 | 192 | ||
193 | impl<T> Gen<T> { | 193 | impl<T> Gen<T> { |
194 | pub fn make() -> Gen<T> { | 194 | pub fn make() -> Gen<T> { |
195 | loop { } | 195 | loop { } |
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | fn test() { | 199 | fn test() { |
200 | let a = Gen::<u32>::make(); | 200 | let a = Gen::<u32>::make(); |
201 | } | 201 | } |
202 | "#), | 202 | "#, |
203 | @r###" | 203 | expect![[r#" |
204 | 75..99 '{ ... }': Gen<T> | 204 | 75..99 '{ ... }': Gen<T> |
205 | 85..93 'loop { }': ! | 205 | 85..93 'loop { }': ! |
206 | 90..93 '{ }': () | 206 | 90..93 '{ }': () |
207 | 113..148 '{ ...e(); }': () | 207 | 113..148 '{ ...e(); }': () |
208 | 123..124 'a': Gen<u32> | 208 | 123..124 'a': Gen<u32> |
209 | 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32> | 209 | 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32> |
210 | 127..145 'Gen::<...make()': Gen<u32> | 210 | 127..145 'Gen::<...make()': Gen<u32> |
211 | "### | 211 | "#]], |
212 | ); | 212 | ); |
213 | } | 213 | } |
214 | 214 | ||
215 | #[test] | 215 | #[test] |
216 | fn infer_associated_method_generics_2_type_params_without_args() { | 216 | fn infer_associated_method_generics_2_type_params_without_args() { |
217 | assert_snapshot!( | 217 | check_infer( |
218 | infer(r#" | 218 | r#" |
219 | struct Gen<T, U> { | 219 | struct Gen<T, U> { |
220 | val: T, | 220 | val: T, |
221 | val2: U, | 221 | val2: U, |
222 | } | 222 | } |
223 | 223 | ||
224 | impl<T> Gen<u32, T> { | 224 | impl<T> Gen<u32, T> { |
225 | pub fn make() -> Gen<u32,T> { | 225 | pub fn make() -> Gen<u32,T> { |
226 | loop { } | 226 | loop { } |
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | fn test() { | 230 | fn test() { |
231 | let a = Gen::<u32, u64>::make(); | 231 | let a = Gen::<u32, u64>::make(); |
232 | } | 232 | } |
233 | "#), | 233 | "#, |
234 | @r###" | 234 | expect![[r#" |
235 | 101..125 '{ ... }': Gen<u32, T> | 235 | 101..125 '{ ... }': Gen<u32, T> |
236 | 111..119 'loop { }': ! | 236 | 111..119 'loop { }': ! |
237 | 116..119 '{ }': () | 237 | 116..119 '{ }': () |
238 | 139..179 '{ ...e(); }': () | 238 | 139..179 '{ ...e(); }': () |
239 | 149..150 'a': Gen<u32, u64> | 239 | 149..150 'a': Gen<u32, u64> |
240 | 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> | 240 | 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> |
241 | 153..176 'Gen::<...make()': Gen<u32, u64> | 241 | 153..176 'Gen::<...make()': Gen<u32, u64> |
242 | "### | 242 | "#]], |
243 | ); | 243 | ); |
244 | } | 244 | } |
245 | 245 | ||
@@ -267,416 +267,416 @@ mod foo { | |||
267 | #[test] | 267 | #[test] |
268 | fn infer_trait_method_simple() { | 268 | fn infer_trait_method_simple() { |
269 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 269 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
270 | assert_snapshot!( | 270 | check_infer( |
271 | infer(r#" | 271 | r#" |
272 | trait Trait1 { | 272 | trait Trait1 { |
273 | fn method(&self) -> u32; | 273 | fn method(&self) -> u32; |
274 | } | 274 | } |
275 | struct S1; | 275 | struct S1; |
276 | impl Trait1 for S1 {} | 276 | impl Trait1 for S1 {} |
277 | trait Trait2 { | 277 | trait Trait2 { |
278 | fn method(&self) -> i128; | 278 | fn method(&self) -> i128; |
279 | } | 279 | } |
280 | struct S2; | 280 | struct S2; |
281 | impl Trait2 for S2 {} | 281 | impl Trait2 for S2 {} |
282 | fn test() { | 282 | fn test() { |
283 | S1.method(); // -> u32 | 283 | S1.method(); // -> u32 |
284 | S2.method(); // -> i128 | 284 | S2.method(); // -> i128 |
285 | } | 285 | } |
286 | "#), | 286 | "#, |
287 | @r###" | 287 | expect![[r#" |
288 | 30..34 'self': &Self | 288 | 30..34 'self': &Self |
289 | 109..113 'self': &Self | 289 | 109..113 'self': &Self |
290 | 169..227 '{ ...i128 }': () | 290 | 169..227 '{ ...i128 }': () |
291 | 175..177 'S1': S1 | 291 | 175..177 'S1': S1 |
292 | 175..186 'S1.method()': u32 | 292 | 175..186 'S1.method()': u32 |
293 | 202..204 'S2': S2 | 293 | 202..204 'S2': S2 |
294 | 202..213 'S2.method()': i128 | 294 | 202..213 'S2.method()': i128 |
295 | "### | 295 | "#]], |
296 | ); | 296 | ); |
297 | } | 297 | } |
298 | 298 | ||
299 | #[test] | 299 | #[test] |
300 | fn infer_trait_method_scoped() { | 300 | fn infer_trait_method_scoped() { |
301 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 301 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
302 | assert_snapshot!( | 302 | check_infer( |
303 | infer(r#" | 303 | r#" |
304 | struct S; | 304 | struct S; |
305 | mod foo { | 305 | mod foo { |
306 | pub trait Trait1 { | 306 | pub trait Trait1 { |
307 | fn method(&self) -> u32; | 307 | fn method(&self) -> u32; |
308 | } | 308 | } |
309 | impl Trait1 for super::S {} | 309 | impl Trait1 for super::S {} |
310 | } | 310 | } |
311 | mod bar { | 311 | mod bar { |
312 | pub trait Trait2 { | 312 | pub trait Trait2 { |
313 | fn method(&self) -> i128; | 313 | fn method(&self) -> i128; |
314 | } | 314 | } |
315 | impl Trait2 for super::S {} | 315 | impl Trait2 for super::S {} |
316 | } | 316 | } |
317 | 317 | ||
318 | mod foo_test { | 318 | mod foo_test { |
319 | use super::S; | 319 | use super::S; |
320 | use super::foo::Trait1; | 320 | use super::foo::Trait1; |
321 | fn test() { | 321 | fn test() { |
322 | S.method(); // -> u32 | 322 | S.method(); // -> u32 |
323 | } | 323 | } |
324 | } | 324 | } |
325 | 325 | ||
326 | mod bar_test { | 326 | mod bar_test { |
327 | use super::S; | 327 | use super::S; |
328 | use super::bar::Trait2; | 328 | use super::bar::Trait2; |
329 | fn test() { | 329 | fn test() { |
330 | S.method(); // -> i128 | 330 | S.method(); // -> i128 |
331 | } | 331 | } |
332 | } | 332 | } |
333 | "#), | 333 | "#, |
334 | @r###" | 334 | expect![[r#" |
335 | 62..66 'self': &Self | 335 | 62..66 'self': &Self |
336 | 168..172 'self': &Self | 336 | 168..172 'self': &Self |
337 | 299..336 '{ ... }': () | 337 | 299..336 '{ ... }': () |
338 | 309..310 'S': S | 338 | 309..310 'S': S |
339 | 309..319 'S.method()': u32 | 339 | 309..319 'S.method()': u32 |
340 | 415..453 '{ ... }': () | 340 | 415..453 '{ ... }': () |
341 | 425..426 'S': S | 341 | 425..426 'S': S |
342 | 425..435 'S.method()': i128 | 342 | 425..435 'S.method()': i128 |
343 | "### | 343 | "#]], |
344 | ); | 344 | ); |
345 | } | 345 | } |
346 | 346 | ||
347 | #[test] | 347 | #[test] |
348 | fn infer_trait_method_generic_1() { | 348 | fn infer_trait_method_generic_1() { |
349 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 349 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
350 | assert_snapshot!( | 350 | check_infer( |
351 | infer(r#" | 351 | r#" |
352 | trait Trait<T> { | 352 | trait Trait<T> { |
353 | fn method(&self) -> T; | 353 | fn method(&self) -> T; |
354 | } | 354 | } |
355 | struct S; | 355 | struct S; |
356 | impl Trait<u32> for S {} | 356 | impl Trait<u32> for S {} |
357 | fn test() { | 357 | fn test() { |
358 | S.method(); | 358 | S.method(); |
359 | } | 359 | } |
360 | "#), | 360 | "#, |
361 | @r###" | 361 | expect![[r#" |
362 | 32..36 'self': &Self | 362 | 32..36 'self': &Self |
363 | 91..110 '{ ...d(); }': () | 363 | 91..110 '{ ...d(); }': () |
364 | 97..98 'S': S | 364 | 97..98 'S': S |
365 | 97..107 'S.method()': u32 | 365 | 97..107 'S.method()': u32 |
366 | "### | 366 | "#]], |
367 | ); | 367 | ); |
368 | } | 368 | } |
369 | 369 | ||
370 | #[test] | 370 | #[test] |
371 | fn infer_trait_method_generic_more_params() { | 371 | fn infer_trait_method_generic_more_params() { |
372 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 372 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
373 | assert_snapshot!( | 373 | check_infer( |
374 | infer(r#" | 374 | r#" |
375 | trait Trait<T1, T2, T3> { | 375 | trait Trait<T1, T2, T3> { |
376 | fn method1(&self) -> (T1, T2, T3); | 376 | fn method1(&self) -> (T1, T2, T3); |
377 | fn method2(&self) -> (T3, T2, T1); | 377 | fn method2(&self) -> (T3, T2, T1); |
378 | } | 378 | } |
379 | struct S1; | 379 | struct S1; |
380 | impl Trait<u8, u16, u32> for S1 {} | 380 | impl Trait<u8, u16, u32> for S1 {} |
381 | struct S2; | 381 | struct S2; |
382 | impl<T> Trait<i8, i16, T> for S2 {} | 382 | impl<T> Trait<i8, i16, T> for S2 {} |
383 | fn test() { | 383 | fn test() { |
384 | S1.method1(); // u8, u16, u32 | 384 | S1.method1(); // u8, u16, u32 |
385 | S1.method2(); // u32, u16, u8 | 385 | S1.method2(); // u32, u16, u8 |
386 | S2.method1(); // i8, i16, {unknown} | 386 | S2.method1(); // i8, i16, {unknown} |
387 | S2.method2(); // {unknown}, i16, i8 | 387 | S2.method2(); // {unknown}, i16, i8 |
388 | } | 388 | } |
389 | "#), | 389 | "#, |
390 | @r###" | 390 | expect![[r#" |
391 | 42..46 'self': &Self | 391 | 42..46 'self': &Self |
392 | 81..85 'self': &Self | 392 | 81..85 'self': &Self |
393 | 209..360 '{ ..., i8 }': () | 393 | 209..360 '{ ..., i8 }': () |
394 | 215..217 'S1': S1 | 394 | 215..217 'S1': S1 |
395 | 215..227 'S1.method1()': (u8, u16, u32) | 395 | 215..227 'S1.method1()': (u8, u16, u32) |
396 | 249..251 'S1': S1 | 396 | 249..251 'S1': S1 |
397 | 249..261 'S1.method2()': (u32, u16, u8) | 397 | 249..261 'S1.method2()': (u32, u16, u8) |
398 | 283..285 'S2': S2 | 398 | 283..285 'S2': S2 |
399 | 283..295 'S2.method1()': (i8, i16, {unknown}) | 399 | 283..295 'S2.method1()': (i8, i16, {unknown}) |
400 | 323..325 'S2': S2 | 400 | 323..325 'S2': S2 |
401 | 323..335 'S2.method2()': ({unknown}, i16, i8) | 401 | 323..335 'S2.method2()': ({unknown}, i16, i8) |
402 | "### | 402 | "#]], |
403 | ); | 403 | ); |
404 | } | 404 | } |
405 | 405 | ||
406 | #[test] | 406 | #[test] |
407 | fn infer_trait_method_generic_2() { | 407 | fn infer_trait_method_generic_2() { |
408 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 408 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
409 | assert_snapshot!( | 409 | check_infer( |
410 | infer(r#" | 410 | r#" |
411 | trait Trait<T> { | 411 | trait Trait<T> { |
412 | fn method(&self) -> T; | 412 | fn method(&self) -> T; |
413 | } | 413 | } |
414 | struct S<T>(T); | 414 | struct S<T>(T); |
415 | impl<U> Trait<U> for S<U> {} | 415 | impl<U> Trait<U> for S<U> {} |
416 | fn test() { | 416 | fn test() { |
417 | S(1u32).method(); | 417 | S(1u32).method(); |
418 | } | 418 | } |
419 | "#), | 419 | "#, |
420 | @r###" | 420 | expect![[r#" |
421 | 32..36 'self': &Self | 421 | 32..36 'self': &Self |
422 | 101..126 '{ ...d(); }': () | 422 | 101..126 '{ ...d(); }': () |
423 | 107..108 'S': S<u32>(u32) -> S<u32> | 423 | 107..108 'S': S<u32>(u32) -> S<u32> |
424 | 107..114 'S(1u32)': S<u32> | 424 | 107..114 'S(1u32)': S<u32> |
425 | 107..123 'S(1u32...thod()': u32 | 425 | 107..123 'S(1u32...thod()': u32 |
426 | 109..113 '1u32': u32 | 426 | 109..113 '1u32': u32 |
427 | "### | 427 | "#]], |
428 | ); | 428 | ); |
429 | } | 429 | } |
430 | 430 | ||
431 | #[test] | 431 | #[test] |
432 | fn infer_trait_assoc_method() { | 432 | fn infer_trait_assoc_method() { |
433 | assert_snapshot!( | 433 | check_infer( |
434 | infer(r#" | 434 | r#" |
435 | trait Default { | 435 | trait Default { |
436 | fn default() -> Self; | 436 | fn default() -> Self; |
437 | } | 437 | } |
438 | struct S; | 438 | struct S; |
439 | impl Default for S {} | 439 | impl Default for S {} |
440 | fn test() { | 440 | fn test() { |
441 | let s1: S = Default::default(); | 441 | let s1: S = Default::default(); |
442 | let s2 = S::default(); | 442 | let s2 = S::default(); |
443 | let s3 = <S as Default>::default(); | 443 | let s3 = <S as Default>::default(); |
444 | } | 444 | } |
445 | "#), | 445 | "#, |
446 | @r###" | 446 | expect![[r#" |
447 | 86..192 '{ ...t(); }': () | 447 | 86..192 '{ ...t(); }': () |
448 | 96..98 's1': S | 448 | 96..98 's1': S |
449 | 104..120 'Defaul...efault': fn default<S>() -> S | 449 | 104..120 'Defaul...efault': fn default<S>() -> S |
450 | 104..122 'Defaul...ault()': S | 450 | 104..122 'Defaul...ault()': S |
451 | 132..134 's2': S | 451 | 132..134 's2': S |
452 | 137..147 'S::default': fn default<S>() -> S | 452 | 137..147 'S::default': fn default<S>() -> S |
453 | 137..149 'S::default()': S | 453 | 137..149 'S::default()': S |
454 | 159..161 's3': S | 454 | 159..161 's3': S |
455 | 164..187 '<S as ...efault': fn default<S>() -> S | 455 | 164..187 '<S as ...efault': fn default<S>() -> S |
456 | 164..189 '<S as ...ault()': S | 456 | 164..189 '<S as ...ault()': S |
457 | "### | 457 | "#]], |
458 | ); | 458 | ); |
459 | } | 459 | } |
460 | 460 | ||
461 | #[test] | 461 | #[test] |
462 | fn infer_trait_assoc_method_generics_1() { | 462 | fn infer_trait_assoc_method_generics_1() { |
463 | assert_snapshot!( | 463 | check_infer( |
464 | infer(r#" | 464 | r#" |
465 | trait Trait<T> { | 465 | trait Trait<T> { |
466 | fn make() -> T; | 466 | fn make() -> T; |
467 | } | 467 | } |
468 | struct S; | 468 | struct S; |
469 | impl Trait<u32> for S {} | 469 | impl Trait<u32> for S {} |
470 | struct G<T>; | 470 | struct G<T>; |
471 | impl<T> Trait<T> for G<T> {} | 471 | impl<T> Trait<T> for G<T> {} |
472 | fn test() { | 472 | fn test() { |
473 | let a = S::make(); | 473 | let a = S::make(); |
474 | let b = G::<u64>::make(); | 474 | let b = G::<u64>::make(); |
475 | let c: f64 = G::make(); | 475 | let c: f64 = G::make(); |
476 | } | 476 | } |
477 | "#), | 477 | "#, |
478 | @r###" | 478 | expect![[r#" |
479 | 126..210 '{ ...e(); }': () | 479 | 126..210 '{ ...e(); }': () |
480 | 136..137 'a': u32 | 480 | 136..137 'a': u32 |
481 | 140..147 'S::make': fn make<S, u32>() -> u32 | 481 | 140..147 'S::make': fn make<S, u32>() -> u32 |
482 | 140..149 'S::make()': u32 | 482 | 140..149 'S::make()': u32 |
483 | 159..160 'b': u64 | 483 | 159..160 'b': u64 |
484 | 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 | 484 | 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 |
485 | 163..179 'G::<u6...make()': u64 | 485 | 163..179 'G::<u6...make()': u64 |
486 | 189..190 'c': f64 | 486 | 189..190 'c': f64 |
487 | 198..205 'G::make': fn make<G<f64>, f64>() -> f64 | 487 | 198..205 'G::make': fn make<G<f64>, f64>() -> f64 |
488 | 198..207 'G::make()': f64 | 488 | 198..207 'G::make()': f64 |
489 | "### | 489 | "#]], |
490 | ); | 490 | ); |
491 | } | 491 | } |
492 | 492 | ||
493 | #[test] | 493 | #[test] |
494 | fn infer_trait_assoc_method_generics_2() { | 494 | fn infer_trait_assoc_method_generics_2() { |
495 | assert_snapshot!( | 495 | check_infer( |
496 | infer(r#" | 496 | r#" |
497 | trait Trait<T> { | 497 | trait Trait<T> { |
498 | fn make<U>() -> (T, U); | 498 | fn make<U>() -> (T, U); |
499 | } | 499 | } |
500 | struct S; | 500 | struct S; |
501 | impl Trait<u32> for S {} | 501 | impl Trait<u32> for S {} |
502 | struct G<T>; | 502 | struct G<T>; |
503 | impl<T> Trait<T> for G<T> {} | 503 | impl<T> Trait<T> for G<T> {} |
504 | fn test() { | 504 | fn test() { |
505 | let a = S::make::<i64>(); | 505 | let a = S::make::<i64>(); |
506 | let b: (_, i64) = S::make(); | 506 | let b: (_, i64) = S::make(); |
507 | let c = G::<u32>::make::<i64>(); | 507 | let c = G::<u32>::make::<i64>(); |
508 | let d: (u32, _) = G::make::<i64>(); | 508 | let d: (u32, _) = G::make::<i64>(); |
509 | let e: (u32, i64) = G::make(); | 509 | let e: (u32, i64) = G::make(); |
510 | } | 510 | } |
511 | "#), | 511 | "#, |
512 | @r###" | 512 | expect![[r#" |
513 | 134..312 '{ ...e(); }': () | 513 | 134..312 '{ ...e(); }': () |
514 | 144..145 'a': (u32, i64) | 514 | 144..145 'a': (u32, i64) |
515 | 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) | 515 | 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) |
516 | 148..164 'S::mak...i64>()': (u32, i64) | 516 | 148..164 'S::mak...i64>()': (u32, i64) |
517 | 174..175 'b': (u32, i64) | 517 | 174..175 'b': (u32, i64) |
518 | 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64) | 518 | 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64) |
519 | 188..197 'S::make()': (u32, i64) | 519 | 188..197 'S::make()': (u32, i64) |
520 | 207..208 'c': (u32, i64) | 520 | 207..208 'c': (u32, i64) |
521 | 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | 521 | 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
522 | 211..234 'G::<u3...i64>()': (u32, i64) | 522 | 211..234 'G::<u3...i64>()': (u32, i64) |
523 | 244..245 'd': (u32, i64) | 523 | 244..245 'd': (u32, i64) |
524 | 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | 524 | 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) |
525 | 258..274 'G::mak...i64>()': (u32, i64) | 525 | 258..274 'G::mak...i64>()': (u32, i64) |
526 | 284..285 'e': (u32, i64) | 526 | 284..285 'e': (u32, i64) |
527 | 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) | 527 | 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) |
528 | 300..309 'G::make()': (u32, i64) | 528 | 300..309 'G::make()': (u32, i64) |
529 | "### | 529 | "#]], |
530 | ); | 530 | ); |
531 | } | 531 | } |
532 | 532 | ||
533 | #[test] | 533 | #[test] |
534 | fn infer_trait_assoc_method_generics_3() { | 534 | fn infer_trait_assoc_method_generics_3() { |
535 | assert_snapshot!( | 535 | check_infer( |
536 | infer(r#" | 536 | r#" |
537 | trait Trait<T> { | 537 | trait Trait<T> { |
538 | fn make() -> (Self, T); | 538 | fn make() -> (Self, T); |
539 | } | 539 | } |
540 | struct S<T>; | 540 | struct S<T>; |
541 | impl Trait<i64> for S<i32> {} | 541 | impl Trait<i64> for S<i32> {} |
542 | fn test() { | 542 | fn test() { |
543 | let a = S::make(); | 543 | let a = S::make(); |
544 | } | 544 | } |
545 | "#), | 545 | "#, |
546 | @r###" | 546 | expect![[r#" |
547 | 100..126 '{ ...e(); }': () | 547 | 100..126 '{ ...e(); }': () |
548 | 110..111 'a': (S<i32>, i64) | 548 | 110..111 'a': (S<i32>, i64) |
549 | 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) | 549 | 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) |
550 | 114..123 'S::make()': (S<i32>, i64) | 550 | 114..123 'S::make()': (S<i32>, i64) |
551 | "### | 551 | "#]], |
552 | ); | 552 | ); |
553 | } | 553 | } |
554 | 554 | ||
555 | #[test] | 555 | #[test] |
556 | fn infer_trait_assoc_method_generics_4() { | 556 | fn infer_trait_assoc_method_generics_4() { |
557 | assert_snapshot!( | 557 | check_infer( |
558 | infer(r#" | 558 | r#" |
559 | trait Trait<T> { | 559 | trait Trait<T> { |
560 | fn make() -> (Self, T); | 560 | fn make() -> (Self, T); |
561 | } | 561 | } |
562 | struct S<T>; | 562 | struct S<T>; |
563 | impl Trait<i64> for S<u64> {} | 563 | impl Trait<i64> for S<u64> {} |
564 | impl Trait<i32> for S<u32> {} | 564 | impl Trait<i32> for S<u32> {} |
565 | fn test() { | 565 | fn test() { |
566 | let a: (S<u64>, _) = S::make(); | 566 | let a: (S<u64>, _) = S::make(); |
567 | let b: (_, i32) = S::make(); | 567 | let b: (_, i32) = S::make(); |
568 | } | 568 | } |
569 | "#), | 569 | "#, |
570 | @r###" | 570 | expect![[r#" |
571 | 130..202 '{ ...e(); }': () | 571 | 130..202 '{ ...e(); }': () |
572 | 140..141 'a': (S<u64>, i64) | 572 | 140..141 'a': (S<u64>, i64) |
573 | 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) | 573 | 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) |
574 | 157..166 'S::make()': (S<u64>, i64) | 574 | 157..166 'S::make()': (S<u64>, i64) |
575 | 176..177 'b': (S<u32>, i32) | 575 | 176..177 'b': (S<u32>, i32) |
576 | 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) | 576 | 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) |
577 | 190..199 'S::make()': (S<u32>, i32) | 577 | 190..199 'S::make()': (S<u32>, i32) |
578 | "### | 578 | "#]], |
579 | ); | 579 | ); |
580 | } | 580 | } |
581 | 581 | ||
582 | #[test] | 582 | #[test] |
583 | fn infer_trait_assoc_method_generics_5() { | 583 | fn infer_trait_assoc_method_generics_5() { |
584 | assert_snapshot!( | 584 | check_infer( |
585 | infer(r#" | 585 | r#" |
586 | trait Trait<T> { | 586 | trait Trait<T> { |
587 | fn make<U>() -> (Self, T, U); | 587 | fn make<U>() -> (Self, T, U); |
588 | } | 588 | } |
589 | struct S<T>; | 589 | struct S<T>; |
590 | impl Trait<i64> for S<u64> {} | 590 | impl Trait<i64> for S<u64> {} |
591 | fn test() { | 591 | fn test() { |
592 | let a = <S as Trait<i64>>::make::<u8>(); | 592 | let a = <S as Trait<i64>>::make::<u8>(); |
593 | let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>(); | 593 | let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>(); |
594 | } | 594 | } |
595 | "#), | 595 | "#, |
596 | @r###" | 596 | expect![[r#" |
597 | 106..210 '{ ...>(); }': () | 597 | 106..210 '{ ...>(); }': () |
598 | 116..117 'a': (S<u64>, i64, u8) | 598 | 116..117 'a': (S<u64>, i64, u8) |
599 | 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | 599 | 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
600 | 120..151 '<S as ...<u8>()': (S<u64>, i64, u8) | 600 | 120..151 '<S as ...<u8>()': (S<u64>, i64, u8) |
601 | 161..162 'b': (S<u64>, i64, u8) | 601 | 161..162 'b': (S<u64>, i64, u8) |
602 | 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | 602 | 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) |
603 | 181..207 'Trait:...<u8>()': (S<u64>, i64, u8) | 603 | 181..207 'Trait:...<u8>()': (S<u64>, i64, u8) |
604 | "### | 604 | "#]], |
605 | ); | 605 | ); |
606 | } | 606 | } |
607 | 607 | ||
608 | #[test] | 608 | #[test] |
609 | fn infer_call_trait_method_on_generic_param_1() { | 609 | fn infer_call_trait_method_on_generic_param_1() { |
610 | assert_snapshot!( | 610 | check_infer( |
611 | infer(r#" | 611 | r#" |
612 | trait Trait { | 612 | trait Trait { |
613 | fn method(&self) -> u32; | 613 | fn method(&self) -> u32; |
614 | } | 614 | } |
615 | fn test<T: Trait>(t: T) { | 615 | fn test<T: Trait>(t: T) { |
616 | t.method(); | 616 | t.method(); |
617 | } | 617 | } |
618 | "#), | 618 | "#, |
619 | @r###" | 619 | expect![[r#" |
620 | 29..33 'self': &Self | 620 | 29..33 'self': &Self |
621 | 63..64 't': T | 621 | 63..64 't': T |
622 | 69..88 '{ ...d(); }': () | 622 | 69..88 '{ ...d(); }': () |
623 | 75..76 't': T | 623 | 75..76 't': T |
624 | 75..85 't.method()': u32 | 624 | 75..85 't.method()': u32 |
625 | "### | 625 | "#]], |
626 | ); | 626 | ); |
627 | } | 627 | } |
628 | 628 | ||
629 | #[test] | 629 | #[test] |
630 | fn infer_call_trait_method_on_generic_param_2() { | 630 | fn infer_call_trait_method_on_generic_param_2() { |
631 | assert_snapshot!( | 631 | check_infer( |
632 | infer(r#" | 632 | r#" |
633 | trait Trait<T> { | 633 | trait Trait<T> { |
634 | fn method(&self) -> T; | 634 | fn method(&self) -> T; |
635 | } | 635 | } |
636 | fn test<U, T: Trait<U>>(t: T) { | 636 | fn test<U, T: Trait<U>>(t: T) { |
637 | t.method(); | 637 | t.method(); |
638 | } | 638 | } |
639 | "#), | 639 | "#, |
640 | @r###" | 640 | expect![[r#" |
641 | 32..36 'self': &Self | 641 | 32..36 'self': &Self |
642 | 70..71 't': T | 642 | 70..71 't': T |
643 | 76..95 '{ ...d(); }': () | 643 | 76..95 '{ ...d(); }': () |
644 | 82..83 't': T | 644 | 82..83 't': T |
645 | 82..92 't.method()': U | 645 | 82..92 't.method()': U |
646 | "### | 646 | "#]], |
647 | ); | 647 | ); |
648 | } | 648 | } |
649 | 649 | ||
650 | #[test] | 650 | #[test] |
651 | fn infer_with_multiple_trait_impls() { | 651 | fn infer_with_multiple_trait_impls() { |
652 | assert_snapshot!( | 652 | check_infer( |
653 | infer(r#" | 653 | r#" |
654 | trait Into<T> { | 654 | trait Into<T> { |
655 | fn into(self) -> T; | 655 | fn into(self) -> T; |
656 | } | 656 | } |
657 | struct S; | 657 | struct S; |
658 | impl Into<u32> for S {} | 658 | impl Into<u32> for S {} |
659 | impl Into<u64> for S {} | 659 | impl Into<u64> for S {} |
660 | fn test() { | 660 | fn test() { |
661 | let x: u32 = S.into(); | 661 | let x: u32 = S.into(); |
662 | let y: u64 = S.into(); | 662 | let y: u64 = S.into(); |
663 | let z = Into::<u64>::into(S); | 663 | let z = Into::<u64>::into(S); |
664 | } | 664 | } |
665 | "#), | 665 | "#, |
666 | @r###" | 666 | expect![[r#" |
667 | 28..32 'self': Self | 667 | 28..32 'self': Self |
668 | 110..201 '{ ...(S); }': () | 668 | 110..201 '{ ...(S); }': () |
669 | 120..121 'x': u32 | 669 | 120..121 'x': u32 |
670 | 129..130 'S': S | 670 | 129..130 'S': S |
671 | 129..137 'S.into()': u32 | 671 | 129..137 'S.into()': u32 |
672 | 147..148 'y': u64 | 672 | 147..148 'y': u64 |
673 | 156..157 'S': S | 673 | 156..157 'S': S |
674 | 156..164 'S.into()': u64 | 674 | 156..164 'S.into()': u64 |
675 | 174..175 'z': u64 | 675 | 174..175 'z': u64 |
676 | 178..195 'Into::...::into': fn into<S, u64>(S) -> u64 | 676 | 178..195 'Into::...::into': fn into<S, u64>(S) -> u64 |
677 | 178..198 'Into::...nto(S)': u64 | 677 | 178..198 'Into::...nto(S)': u64 |
678 | 196..197 'S': S | 678 | 196..197 'S': S |
679 | "### | 679 | "#]], |
680 | ); | 680 | ); |
681 | } | 681 | } |
682 | 682 | ||
@@ -1023,31 +1023,31 @@ fn test() { (S {}).method(); } | |||
1023 | 1023 | ||
1024 | #[test] | 1024 | #[test] |
1025 | fn dyn_trait_super_trait_not_in_scope() { | 1025 | fn dyn_trait_super_trait_not_in_scope() { |
1026 | assert_snapshot!( | 1026 | check_infer( |
1027 | infer(r#" | 1027 | r#" |
1028 | mod m { | 1028 | mod m { |
1029 | pub trait SuperTrait { | 1029 | pub trait SuperTrait { |
1030 | fn foo(&self) -> u32 { 0 } | 1030 | fn foo(&self) -> u32 { 0 } |
1031 | } | 1031 | } |
1032 | } | 1032 | } |
1033 | trait Trait: m::SuperTrait {} | 1033 | trait Trait: m::SuperTrait {} |
1034 | 1034 | ||
1035 | struct S; | 1035 | struct S; |
1036 | impl m::SuperTrait for S {} | 1036 | impl m::SuperTrait for S {} |
1037 | impl Trait for S {} | 1037 | impl Trait for S {} |
1038 | 1038 | ||
1039 | fn test(d: &dyn Trait) { | 1039 | fn test(d: &dyn Trait) { |
1040 | d.foo(); | 1040 | d.foo(); |
1041 | } | 1041 | } |
1042 | "#), | 1042 | "#, |
1043 | @r###" | 1043 | expect![[r#" |
1044 | 51..55 'self': &Self | 1044 | 51..55 'self': &Self |
1045 | 64..69 '{ 0 }': u32 | 1045 | 64..69 '{ 0 }': u32 |
1046 | 66..67 '0': u32 | 1046 | 66..67 '0': u32 |
1047 | 176..177 'd': &dyn Trait | 1047 | 176..177 'd': &dyn Trait |
1048 | 191..207 '{ ...o(); }': () | 1048 | 191..207 '{ ...o(); }': () |
1049 | 197..198 'd': &dyn Trait | 1049 | 197..198 'd': &dyn Trait |
1050 | 197..204 'd.foo()': u32 | 1050 | 197..204 'd.foo()': u32 |
1051 | "### | 1051 | "#]], |
1052 | ); | 1052 | ); |
1053 | } | 1053 | } |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index f937426bd..39fabf7eb 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -1,561 +1,561 @@ | |||
1 | use insta::assert_snapshot; | 1 | use expect::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{infer, infer_with_mismatches}; | 4 | use super::{check_infer, check_infer_with_mismatches}; |
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn infer_pattern() { | 7 | fn infer_pattern() { |
8 | assert_snapshot!( | 8 | check_infer( |
9 | infer(r#" | 9 | r#" |
10 | fn test(x: &i32) { | 10 | fn test(x: &i32) { |
11 | let y = x; | 11 | let y = x; |
12 | let &z = x; | 12 | let &z = x; |
13 | let a = z; | 13 | let a = z; |
14 | let (c, d) = (1, "hello"); | 14 | let (c, d) = (1, "hello"); |
15 | 15 | ||
16 | for (e, f) in some_iter { | 16 | for (e, f) in some_iter { |
17 | let g = e; | 17 | let g = e; |
18 | } | 18 | } |
19 | 19 | ||
20 | if let [val] = opt { | 20 | if let [val] = opt { |
21 | let h = val; | 21 | let h = val; |
22 | } | 22 | } |
23 | 23 | ||
24 | let lambda = |a: u64, b, c: i32| { a + b; c }; | 24 | let lambda = |a: u64, b, c: i32| { a + b; c }; |
25 | 25 | ||
26 | let ref ref_to_x = x; | 26 | let ref ref_to_x = x; |
27 | let mut mut_x = x; | 27 | let mut mut_x = x; |
28 | let ref mut mut_ref_to_x = x; | 28 | let ref mut mut_ref_to_x = x; |
29 | let k = mut_ref_to_x; | 29 | let k = mut_ref_to_x; |
30 | } | 30 | } |
31 | "#), | 31 | "#, |
32 | @r###" | 32 | expect![[r#" |
33 | 8..9 'x': &i32 | 33 | 8..9 'x': &i32 |
34 | 17..368 '{ ...o_x; }': () | 34 | 17..368 '{ ...o_x; }': () |
35 | 27..28 'y': &i32 | 35 | 27..28 'y': &i32 |
36 | 31..32 'x': &i32 | 36 | 31..32 'x': &i32 |
37 | 42..44 '&z': &i32 | 37 | 42..44 '&z': &i32 |
38 | 43..44 'z': i32 | 38 | 43..44 'z': i32 |
39 | 47..48 'x': &i32 | 39 | 47..48 'x': &i32 |
40 | 58..59 'a': i32 | 40 | 58..59 'a': i32 |
41 | 62..63 'z': i32 | 41 | 62..63 'z': i32 |
42 | 73..79 '(c, d)': (i32, &str) | 42 | 73..79 '(c, d)': (i32, &str) |
43 | 74..75 'c': i32 | 43 | 74..75 'c': i32 |
44 | 77..78 'd': &str | 44 | 77..78 'd': &str |
45 | 82..94 '(1, "hello")': (i32, &str) | 45 | 82..94 '(1, "hello")': (i32, &str) |
46 | 83..84 '1': i32 | 46 | 83..84 '1': i32 |
47 | 86..93 '"hello"': &str | 47 | 86..93 '"hello"': &str |
48 | 101..151 'for (e... }': () | 48 | 101..151 'for (e... }': () |
49 | 105..111 '(e, f)': ({unknown}, {unknown}) | 49 | 105..111 '(e, f)': ({unknown}, {unknown}) |
50 | 106..107 'e': {unknown} | 50 | 106..107 'e': {unknown} |
51 | 109..110 'f': {unknown} | 51 | 109..110 'f': {unknown} |
52 | 115..124 'some_iter': {unknown} | 52 | 115..124 'some_iter': {unknown} |
53 | 125..151 '{ ... }': () | 53 | 125..151 '{ ... }': () |
54 | 139..140 'g': {unknown} | 54 | 139..140 'g': {unknown} |
55 | 143..144 'e': {unknown} | 55 | 143..144 'e': {unknown} |
56 | 157..204 'if let... }': () | 56 | 157..204 'if let... }': () |
57 | 164..169 '[val]': [{unknown}] | 57 | 164..169 '[val]': [{unknown}] |
58 | 165..168 'val': {unknown} | 58 | 165..168 'val': {unknown} |
59 | 172..175 'opt': [{unknown}] | 59 | 172..175 'opt': [{unknown}] |
60 | 176..204 '{ ... }': () | 60 | 176..204 '{ ... }': () |
61 | 190..191 'h': {unknown} | 61 | 190..191 'h': {unknown} |
62 | 194..197 'val': {unknown} | 62 | 194..197 'val': {unknown} |
63 | 214..220 'lambda': |u64, u64, i32| -> i32 | 63 | 214..220 'lambda': |u64, u64, i32| -> i32 |
64 | 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32 | 64 | 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32 |
65 | 224..225 'a': u64 | 65 | 224..225 'a': u64 |
66 | 232..233 'b': u64 | 66 | 232..233 'b': u64 |
67 | 235..236 'c': i32 | 67 | 235..236 'c': i32 |
68 | 243..255 '{ a + b; c }': i32 | 68 | 243..255 '{ a + b; c }': i32 |
69 | 245..246 'a': u64 | 69 | 245..246 'a': u64 |
70 | 245..250 'a + b': u64 | 70 | 245..250 'a + b': u64 |
71 | 249..250 'b': u64 | 71 | 249..250 'b': u64 |
72 | 252..253 'c': i32 | 72 | 252..253 'c': i32 |
73 | 266..278 'ref ref_to_x': &&i32 | 73 | 266..278 'ref ref_to_x': &&i32 |
74 | 281..282 'x': &i32 | 74 | 281..282 'x': &i32 |
75 | 292..301 'mut mut_x': &i32 | 75 | 292..301 'mut mut_x': &i32 |
76 | 304..305 'x': &i32 | 76 | 304..305 'x': &i32 |
77 | 315..335 'ref mu...f_to_x': &mut &i32 | 77 | 315..335 'ref mu...f_to_x': &mut &i32 |
78 | 338..339 'x': &i32 | 78 | 338..339 'x': &i32 |
79 | 349..350 'k': &mut &i32 | 79 | 349..350 'k': &mut &i32 |
80 | 353..365 'mut_ref_to_x': &mut &i32 | 80 | 353..365 'mut_ref_to_x': &mut &i32 |
81 | "### | 81 | "#]], |
82 | ); | 82 | ); |
83 | } | 83 | } |
84 | 84 | ||
85 | #[test] | 85 | #[test] |
86 | fn infer_literal_pattern() { | 86 | fn infer_literal_pattern() { |
87 | assert_snapshot!( | 87 | check_infer_with_mismatches( |
88 | infer_with_mismatches(r#" | 88 | r#" |
89 | fn any<T>() -> T { loop {} } | 89 | fn any<T>() -> T { loop {} } |
90 | fn test(x: &i32) { | 90 | fn test(x: &i32) { |
91 | if let "foo" = any() {} | 91 | if let "foo" = any() {} |
92 | if let 1 = any() {} | 92 | if let 1 = any() {} |
93 | if let 1u32 = any() {} | 93 | if let 1u32 = any() {} |
94 | if let 1f32 = any() {} | 94 | if let 1f32 = any() {} |
95 | if let 1.0 = any() {} | 95 | if let 1.0 = any() {} |
96 | if let true = any() {} | 96 | if let true = any() {} |
97 | } | 97 | } |
98 | "#, true), | 98 | "#, |
99 | @r###" | 99 | expect![[r#" |
100 | 17..28 '{ loop {} }': T | 100 | 17..28 '{ loop {} }': T |
101 | 19..26 'loop {}': ! | 101 | 19..26 'loop {}': ! |
102 | 24..26 '{}': () | 102 | 24..26 '{}': () |
103 | 37..38 'x': &i32 | 103 | 37..38 'x': &i32 |
104 | 46..208 '{ ...) {} }': () | 104 | 46..208 '{ ...) {} }': () |
105 | 52..75 'if let...y() {}': () | 105 | 52..75 'if let...y() {}': () |
106 | 59..64 '"foo"': &str | 106 | 59..64 '"foo"': &str |
107 | 59..64 '"foo"': &str | 107 | 59..64 '"foo"': &str |
108 | 67..70 'any': fn any<&str>() -> &str | 108 | 67..70 'any': fn any<&str>() -> &str |
109 | 67..72 'any()': &str | 109 | 67..72 'any()': &str |
110 | 73..75 '{}': () | 110 | 73..75 '{}': () |
111 | 80..99 'if let...y() {}': () | 111 | 80..99 'if let...y() {}': () |
112 | 87..88 '1': i32 | 112 | 87..88 '1': i32 |
113 | 87..88 '1': i32 | 113 | 87..88 '1': i32 |
114 | 91..94 'any': fn any<i32>() -> i32 | 114 | 91..94 'any': fn any<i32>() -> i32 |
115 | 91..96 'any()': i32 | 115 | 91..96 'any()': i32 |
116 | 97..99 '{}': () | 116 | 97..99 '{}': () |
117 | 104..126 'if let...y() {}': () | 117 | 104..126 'if let...y() {}': () |
118 | 111..115 '1u32': u32 | 118 | 111..115 '1u32': u32 |
119 | 111..115 '1u32': u32 | 119 | 111..115 '1u32': u32 |
120 | 118..121 'any': fn any<u32>() -> u32 | 120 | 118..121 'any': fn any<u32>() -> u32 |
121 | 118..123 'any()': u32 | 121 | 118..123 'any()': u32 |
122 | 124..126 '{}': () | 122 | 124..126 '{}': () |
123 | 131..153 'if let...y() {}': () | 123 | 131..153 'if let...y() {}': () |
124 | 138..142 '1f32': f32 | 124 | 138..142 '1f32': f32 |
125 | 138..142 '1f32': f32 | 125 | 138..142 '1f32': f32 |
126 | 145..148 'any': fn any<f32>() -> f32 | 126 | 145..148 'any': fn any<f32>() -> f32 |
127 | 145..150 'any()': f32 | 127 | 145..150 'any()': f32 |
128 | 151..153 '{}': () | 128 | 151..153 '{}': () |
129 | 158..179 'if let...y() {}': () | 129 | 158..179 'if let...y() {}': () |
130 | 165..168 '1.0': f64 | 130 | 165..168 '1.0': f64 |
131 | 165..168 '1.0': f64 | 131 | 165..168 '1.0': f64 |
132 | 171..174 'any': fn any<f64>() -> f64 | 132 | 171..174 'any': fn any<f64>() -> f64 |
133 | 171..176 'any()': f64 | 133 | 171..176 'any()': f64 |
134 | 177..179 '{}': () | 134 | 177..179 '{}': () |
135 | 184..206 'if let...y() {}': () | 135 | 184..206 'if let...y() {}': () |
136 | 191..195 'true': bool | 136 | 191..195 'true': bool |
137 | 191..195 'true': bool | 137 | 191..195 'true': bool |
138 | 198..201 'any': fn any<bool>() -> bool | 138 | 198..201 'any': fn any<bool>() -> bool |
139 | 198..203 'any()': bool | 139 | 198..203 'any()': bool |
140 | 204..206 '{}': () | 140 | 204..206 '{}': () |
141 | "### | 141 | "#]], |
142 | ); | 142 | ); |
143 | } | 143 | } |
144 | 144 | ||
145 | #[test] | 145 | #[test] |
146 | fn infer_range_pattern() { | 146 | fn infer_range_pattern() { |
147 | assert_snapshot!( | 147 | check_infer_with_mismatches( |
148 | infer_with_mismatches(r#" | 148 | r#" |
149 | fn test(x: &i32) { | 149 | fn test(x: &i32) { |
150 | if let 1..76 = 2u32 {} | 150 | if let 1..76 = 2u32 {} |
151 | if let 1..=76 = 2u32 {} | 151 | if let 1..=76 = 2u32 {} |
152 | } | 152 | } |
153 | "#, true), | 153 | "#, |
154 | @r###" | 154 | expect![[r#" |
155 | 8..9 'x': &i32 | 155 | 8..9 'x': &i32 |
156 | 17..75 '{ ...2 {} }': () | 156 | 17..75 '{ ...2 {} }': () |
157 | 23..45 'if let...u32 {}': () | 157 | 23..45 'if let...u32 {}': () |
158 | 30..35 '1..76': u32 | 158 | 30..35 '1..76': u32 |
159 | 38..42 '2u32': u32 | 159 | 38..42 '2u32': u32 |
160 | 43..45 '{}': () | 160 | 43..45 '{}': () |
161 | 50..73 'if let...u32 {}': () | 161 | 50..73 'if let...u32 {}': () |
162 | 57..63 '1..=76': u32 | 162 | 57..63 '1..=76': u32 |
163 | 66..70 '2u32': u32 | 163 | 66..70 '2u32': u32 |
164 | 71..73 '{}': () | 164 | 71..73 '{}': () |
165 | "### | 165 | "#]], |
166 | ); | 166 | ); |
167 | } | 167 | } |
168 | 168 | ||
169 | #[test] | 169 | #[test] |
170 | fn infer_pattern_match_ergonomics() { | 170 | fn infer_pattern_match_ergonomics() { |
171 | assert_snapshot!( | 171 | check_infer( |
172 | infer(r#" | 172 | r#" |
173 | struct A<T>(T); | 173 | struct A<T>(T); |
174 | 174 | ||
175 | fn test() { | 175 | fn test() { |
176 | let A(n) = &A(1); | 176 | let A(n) = &A(1); |
177 | let A(n) = &mut A(1); | 177 | let A(n) = &mut A(1); |
178 | } | 178 | } |
179 | "#), | 179 | "#, |
180 | @r###" | 180 | expect![[r#" |
181 | 27..78 '{ ...(1); }': () | 181 | 27..78 '{ ...(1); }': () |
182 | 37..41 'A(n)': A<i32> | 182 | 37..41 'A(n)': A<i32> |
183 | 39..40 'n': &i32 | 183 | 39..40 'n': &i32 |
184 | 44..49 '&A(1)': &A<i32> | 184 | 44..49 '&A(1)': &A<i32> |
185 | 45..46 'A': A<i32>(i32) -> A<i32> | 185 | 45..46 'A': A<i32>(i32) -> A<i32> |
186 | 45..49 'A(1)': A<i32> | 186 | 45..49 'A(1)': A<i32> |
187 | 47..48 '1': i32 | 187 | 47..48 '1': i32 |
188 | 59..63 'A(n)': A<i32> | 188 | 59..63 'A(n)': A<i32> |
189 | 61..62 'n': &mut i32 | 189 | 61..62 'n': &mut i32 |
190 | 66..75 '&mut A(1)': &mut A<i32> | 190 | 66..75 '&mut A(1)': &mut A<i32> |
191 | 71..72 'A': A<i32>(i32) -> A<i32> | 191 | 71..72 'A': A<i32>(i32) -> A<i32> |
192 | 71..75 'A(1)': A<i32> | 192 | 71..75 'A(1)': A<i32> |
193 | 73..74 '1': i32 | 193 | 73..74 '1': i32 |
194 | "### | 194 | "#]], |
195 | ); | 195 | ); |
196 | } | 196 | } |
197 | 197 | ||
198 | #[test] | 198 | #[test] |
199 | fn infer_pattern_match_ergonomics_ref() { | 199 | fn infer_pattern_match_ergonomics_ref() { |
200 | mark::check!(match_ergonomics_ref); | 200 | mark::check!(match_ergonomics_ref); |
201 | assert_snapshot!( | 201 | check_infer( |
202 | infer(r#" | 202 | r#" |
203 | fn test() { | 203 | fn test() { |
204 | let v = &(1, &2); | 204 | let v = &(1, &2); |
205 | let (_, &w) = v; | 205 | let (_, &w) = v; |
206 | } | 206 | } |
207 | "#), | 207 | "#, |
208 | @r###" | 208 | expect![[r#" |
209 | 10..56 '{ ...= v; }': () | 209 | 10..56 '{ ...= v; }': () |
210 | 20..21 'v': &(i32, &i32) | 210 | 20..21 'v': &(i32, &i32) |
211 | 24..32 '&(1, &2)': &(i32, &i32) | 211 | 24..32 '&(1, &2)': &(i32, &i32) |
212 | 25..32 '(1, &2)': (i32, &i32) | 212 | 25..32 '(1, &2)': (i32, &i32) |
213 | 26..27 '1': i32 | 213 | 26..27 '1': i32 |
214 | 29..31 '&2': &i32 | 214 | 29..31 '&2': &i32 |
215 | 30..31 '2': i32 | 215 | 30..31 '2': i32 |
216 | 42..49 '(_, &w)': (i32, &i32) | 216 | 42..49 '(_, &w)': (i32, &i32) |
217 | 43..44 '_': i32 | 217 | 43..44 '_': i32 |
218 | 46..48 '&w': &i32 | 218 | 46..48 '&w': &i32 |
219 | 47..48 'w': i32 | 219 | 47..48 'w': i32 |
220 | 52..53 'v': &(i32, &i32) | 220 | 52..53 'v': &(i32, &i32) |
221 | "### | 221 | "#]], |
222 | ); | 222 | ); |
223 | } | 223 | } |
224 | 224 | ||
225 | #[test] | 225 | #[test] |
226 | fn infer_pattern_match_slice() { | 226 | fn infer_pattern_match_slice() { |
227 | assert_snapshot!( | 227 | check_infer( |
228 | infer(r#" | 228 | r#" |
229 | fn test() { | 229 | fn test() { |
230 | let slice: &[f64] = &[0.0]; | 230 | let slice: &[f64] = &[0.0]; |
231 | match slice { | 231 | match slice { |
232 | &[] => {}, | 232 | &[] => {}, |
233 | &[a] => { | 233 | &[a] => { |
234 | a; | 234 | a; |
235 | }, | 235 | }, |
236 | &[b, c] => { | 236 | &[b, c] => { |
237 | b; | 237 | b; |
238 | c; | 238 | c; |
239 | } | ||
240 | _ => {} | ||
241 | } | ||
239 | } | 242 | } |
240 | _ => {} | 243 | "#, |
241 | } | 244 | expect![[r#" |
242 | } | 245 | 10..209 '{ ... } }': () |
243 | "#), | 246 | 20..25 'slice': &[f64] |
244 | @r###" | 247 | 36..42 '&[0.0]': &[f64; _] |
245 | 10..209 '{ ... } }': () | 248 | 37..42 '[0.0]': [f64; _] |
246 | 20..25 'slice': &[f64] | 249 | 38..41 '0.0': f64 |
247 | 36..42 '&[0.0]': &[f64; _] | 250 | 48..207 'match ... }': () |
248 | 37..42 '[0.0]': [f64; _] | 251 | 54..59 'slice': &[f64] |
249 | 38..41 '0.0': f64 | 252 | 70..73 '&[]': &[f64] |
250 | 48..207 'match ... }': () | 253 | 71..73 '[]': [f64] |
251 | 54..59 'slice': &[f64] | 254 | 77..79 '{}': () |
252 | 70..73 '&[]': &[f64] | 255 | 89..93 '&[a]': &[f64] |
253 | 71..73 '[]': [f64] | 256 | 90..93 '[a]': [f64] |
254 | 77..79 '{}': () | 257 | 91..92 'a': f64 |
255 | 89..93 '&[a]': &[f64] | 258 | 97..123 '{ ... }': () |
256 | 90..93 '[a]': [f64] | 259 | 111..112 'a': f64 |
257 | 91..92 'a': f64 | 260 | 133..140 '&[b, c]': &[f64] |
258 | 97..123 '{ ... }': () | 261 | 134..140 '[b, c]': [f64] |
259 | 111..112 'a': f64 | 262 | 135..136 'b': f64 |
260 | 133..140 '&[b, c]': &[f64] | 263 | 138..139 'c': f64 |
261 | 134..140 '[b, c]': [f64] | 264 | 144..185 '{ ... }': () |
262 | 135..136 'b': f64 | 265 | 158..159 'b': f64 |
263 | 138..139 'c': f64 | 266 | 173..174 'c': f64 |
264 | 144..185 '{ ... }': () | 267 | 194..195 '_': &[f64] |
265 | 158..159 'b': f64 | 268 | 199..201 '{}': () |
266 | 173..174 'c': f64 | 269 | "#]], |
267 | 194..195 '_': &[f64] | ||
268 | 199..201 '{}': () | ||
269 | "### | ||
270 | ); | 270 | ); |
271 | } | 271 | } |
272 | 272 | ||
273 | #[test] | 273 | #[test] |
274 | fn infer_pattern_match_string_literal() { | 274 | fn infer_pattern_match_string_literal() { |
275 | assert_snapshot!( | 275 | check_infer_with_mismatches( |
276 | infer_with_mismatches(r#" | 276 | r#" |
277 | fn test() { | 277 | fn test() { |
278 | let s: &str = "hello"; | 278 | let s: &str = "hello"; |
279 | match s { | 279 | match s { |
280 | "hello" => {} | 280 | "hello" => {} |
281 | _ => {} | 281 | _ => {} |
282 | } | 282 | } |
283 | } | 283 | } |
284 | "#, true), | 284 | "#, |
285 | @r###" | 285 | expect![[r#" |
286 | 10..98 '{ ... } }': () | 286 | 10..98 '{ ... } }': () |
287 | 20..21 's': &str | 287 | 20..21 's': &str |
288 | 30..37 '"hello"': &str | 288 | 30..37 '"hello"': &str |
289 | 43..96 'match ... }': () | 289 | 43..96 'match ... }': () |
290 | 49..50 's': &str | 290 | 49..50 's': &str |
291 | 61..68 '"hello"': &str | 291 | 61..68 '"hello"': &str |
292 | 61..68 '"hello"': &str | 292 | 61..68 '"hello"': &str |
293 | 72..74 '{}': () | 293 | 72..74 '{}': () |
294 | 83..84 '_': &str | 294 | 83..84 '_': &str |
295 | 88..90 '{}': () | 295 | 88..90 '{}': () |
296 | "### | 296 | "#]], |
297 | ); | 297 | ); |
298 | } | 298 | } |
299 | 299 | ||
300 | #[test] | 300 | #[test] |
301 | fn infer_pattern_match_or() { | 301 | fn infer_pattern_match_or() { |
302 | assert_snapshot!( | 302 | check_infer_with_mismatches( |
303 | infer_with_mismatches(r#" | 303 | r#" |
304 | fn test() { | 304 | fn test() { |
305 | let s: &str = "hello"; | 305 | let s: &str = "hello"; |
306 | match s { | 306 | match s { |
307 | "hello" | "world" => {} | 307 | "hello" | "world" => {} |
308 | _ => {} | 308 | _ => {} |
309 | } | 309 | } |
310 | } | 310 | } |
311 | "#, true), | 311 | "#, |
312 | @r###" | 312 | expect![[r#" |
313 | 10..108 '{ ... } }': () | 313 | 10..108 '{ ... } }': () |
314 | 20..21 's': &str | 314 | 20..21 's': &str |
315 | 30..37 '"hello"': &str | 315 | 30..37 '"hello"': &str |
316 | 43..106 'match ... }': () | 316 | 43..106 'match ... }': () |
317 | 49..50 's': &str | 317 | 49..50 's': &str |
318 | 61..68 '"hello"': &str | 318 | 61..68 '"hello"': &str |
319 | 61..68 '"hello"': &str | 319 | 61..68 '"hello"': &str |
320 | 61..78 '"hello...world"': &str | 320 | 61..78 '"hello...world"': &str |
321 | 71..78 '"world"': &str | 321 | 71..78 '"world"': &str |
322 | 71..78 '"world"': &str | 322 | 71..78 '"world"': &str |
323 | 82..84 '{}': () | 323 | 82..84 '{}': () |
324 | 93..94 '_': &str | 324 | 93..94 '_': &str |
325 | 98..100 '{}': () | 325 | 98..100 '{}': () |
326 | "### | 326 | "#]], |
327 | ); | 327 | ); |
328 | } | 328 | } |
329 | 329 | ||
330 | #[test] | 330 | #[test] |
331 | fn infer_pattern_match_arr() { | 331 | fn infer_pattern_match_arr() { |
332 | assert_snapshot!( | 332 | check_infer( |
333 | infer(r#" | 333 | r#" |
334 | fn test() { | 334 | fn test() { |
335 | let arr: [f64; 2] = [0.0, 1.0]; | 335 | let arr: [f64; 2] = [0.0, 1.0]; |
336 | match arr { | 336 | match arr { |
337 | [1.0, a] => { | 337 | [1.0, a] => { |
338 | a; | 338 | a; |
339 | }, | 339 | }, |
340 | [b, c] => { | 340 | [b, c] => { |
341 | b; | 341 | b; |
342 | c; | 342 | c; |
343 | } | ||
344 | } | ||
343 | } | 345 | } |
344 | } | 346 | "#, |
345 | } | 347 | expect![[r#" |
346 | "#), | 348 | 10..179 '{ ... } }': () |
347 | @r###" | 349 | 20..23 'arr': [f64; _] |
348 | 10..179 '{ ... } }': () | 350 | 36..46 '[0.0, 1.0]': [f64; _] |
349 | 20..23 'arr': [f64; _] | 351 | 37..40 '0.0': f64 |
350 | 36..46 '[0.0, 1.0]': [f64; _] | 352 | 42..45 '1.0': f64 |
351 | 37..40 '0.0': f64 | 353 | 52..177 'match ... }': () |
352 | 42..45 '1.0': f64 | 354 | 58..61 'arr': [f64; _] |
353 | 52..177 'match ... }': () | 355 | 72..80 '[1.0, a]': [f64; _] |
354 | 58..61 'arr': [f64; _] | 356 | 73..76 '1.0': f64 |
355 | 72..80 '[1.0, a]': [f64; _] | 357 | 73..76 '1.0': f64 |
356 | 73..76 '1.0': f64 | 358 | 78..79 'a': f64 |
357 | 73..76 '1.0': f64 | 359 | 84..110 '{ ... }': () |
358 | 78..79 'a': f64 | 360 | 98..99 'a': f64 |
359 | 84..110 '{ ... }': () | 361 | 120..126 '[b, c]': [f64; _] |
360 | 98..99 'a': f64 | 362 | 121..122 'b': f64 |
361 | 120..126 '[b, c]': [f64; _] | 363 | 124..125 'c': f64 |
362 | 121..122 'b': f64 | 364 | 130..171 '{ ... }': () |
363 | 124..125 'c': f64 | 365 | 144..145 'b': f64 |
364 | 130..171 '{ ... }': () | 366 | 159..160 'c': f64 |
365 | 144..145 'b': f64 | 367 | "#]], |
366 | 159..160 'c': f64 | ||
367 | "### | ||
368 | ); | 368 | ); |
369 | } | 369 | } |
370 | 370 | ||
371 | #[test] | 371 | #[test] |
372 | fn infer_adt_pattern() { | 372 | fn infer_adt_pattern() { |
373 | assert_snapshot!( | 373 | check_infer( |
374 | infer(r#" | 374 | r#" |
375 | enum E { | 375 | enum E { |
376 | A { x: usize }, | 376 | A { x: usize }, |
377 | B | 377 | B |
378 | } | 378 | } |
379 | 379 | ||
380 | struct S(u32, E); | 380 | struct S(u32, E); |
381 | 381 | ||
382 | fn test() { | 382 | fn test() { |
383 | let e = E::A { x: 3 }; | 383 | let e = E::A { x: 3 }; |
384 | 384 | ||
385 | let S(y, z) = foo; | 385 | let S(y, z) = foo; |
386 | let E::A { x: new_var } = e; | 386 | let E::A { x: new_var } = e; |
387 | 387 | ||
388 | match e { | 388 | match e { |
389 | E::A { x } => x, | 389 | E::A { x } => x, |
390 | E::B if foo => 1, | 390 | E::B if foo => 1, |
391 | E::B => 10, | 391 | E::B => 10, |
392 | }; | 392 | }; |
393 | 393 | ||
394 | let ref d @ E::A { .. } = e; | 394 | let ref d @ E::A { .. } = e; |
395 | d; | 395 | d; |
396 | } | 396 | } |
397 | "#), | 397 | "#, |
398 | @r###" | 398 | expect![[r#" |
399 | 67..288 '{ ... d; }': () | 399 | 67..288 '{ ... d; }': () |
400 | 77..78 'e': E | 400 | 77..78 'e': E |
401 | 81..94 'E::A { x: 3 }': E | 401 | 81..94 'E::A { x: 3 }': E |
402 | 91..92 '3': usize | 402 | 91..92 '3': usize |
403 | 105..112 'S(y, z)': S | 403 | 105..112 'S(y, z)': S |
404 | 107..108 'y': u32 | 404 | 107..108 'y': u32 |
405 | 110..111 'z': E | 405 | 110..111 'z': E |
406 | 115..118 'foo': S | 406 | 115..118 'foo': S |
407 | 128..147 'E::A {..._var }': E | 407 | 128..147 'E::A {..._var }': E |
408 | 138..145 'new_var': usize | 408 | 138..145 'new_var': usize |
409 | 150..151 'e': E | 409 | 150..151 'e': E |
410 | 158..244 'match ... }': usize | 410 | 158..244 'match ... }': usize |
411 | 164..165 'e': E | 411 | 164..165 'e': E |
412 | 176..186 'E::A { x }': E | 412 | 176..186 'E::A { x }': E |
413 | 183..184 'x': usize | 413 | 183..184 'x': usize |
414 | 190..191 'x': usize | 414 | 190..191 'x': usize |
415 | 201..205 'E::B': E | 415 | 201..205 'E::B': E |
416 | 209..212 'foo': bool | 416 | 209..212 'foo': bool |
417 | 216..217 '1': usize | 417 | 216..217 '1': usize |
418 | 227..231 'E::B': E | 418 | 227..231 'E::B': E |
419 | 235..237 '10': usize | 419 | 235..237 '10': usize |
420 | 255..274 'ref d ...{ .. }': &E | 420 | 255..274 'ref d ...{ .. }': &E |
421 | 263..274 'E::A { .. }': E | 421 | 263..274 'E::A { .. }': E |
422 | 277..278 'e': E | 422 | 277..278 'e': E |
423 | 284..285 'd': &E | 423 | 284..285 'd': &E |
424 | "### | 424 | "#]], |
425 | ); | 425 | ); |
426 | } | 426 | } |
427 | 427 | ||
428 | #[test] | 428 | #[test] |
429 | fn enum_variant_through_self_in_pattern() { | 429 | fn enum_variant_through_self_in_pattern() { |
430 | assert_snapshot!( | 430 | check_infer( |
431 | infer(r#" | 431 | r#" |
432 | enum E { | 432 | enum E { |
433 | A { x: usize }, | 433 | A { x: usize }, |
434 | B(usize), | 434 | B(usize), |
435 | C | 435 | C |
436 | } | 436 | } |
437 | 437 | ||
438 | impl E { | 438 | impl E { |
439 | fn test() { | 439 | fn test() { |
440 | match (loop {}) { | 440 | match (loop {}) { |
441 | Self::A { x } => { x; }, | 441 | Self::A { x } => { x; }, |
442 | Self::B(x) => { x; }, | 442 | Self::B(x) => { x; }, |
443 | Self::C => {}, | 443 | Self::C => {}, |
444 | }; | 444 | }; |
445 | } | 445 | } |
446 | } | 446 | } |
447 | "#), | 447 | "#, |
448 | @r###" | 448 | expect![[r#" |
449 | 75..217 '{ ... }': () | 449 | 75..217 '{ ... }': () |
450 | 85..210 'match ... }': () | 450 | 85..210 'match ... }': () |
451 | 92..99 'loop {}': ! | 451 | 92..99 'loop {}': ! |
452 | 97..99 '{}': () | 452 | 97..99 '{}': () |
453 | 115..128 'Self::A { x }': E | 453 | 115..128 'Self::A { x }': E |
454 | 125..126 'x': usize | 454 | 125..126 'x': usize |
455 | 132..138 '{ x; }': () | 455 | 132..138 '{ x; }': () |
456 | 134..135 'x': usize | 456 | 134..135 'x': usize |
457 | 152..162 'Self::B(x)': E | 457 | 152..162 'Self::B(x)': E |
458 | 160..161 'x': usize | 458 | 160..161 'x': usize |
459 | 166..172 '{ x; }': () | 459 | 166..172 '{ x; }': () |
460 | 168..169 'x': usize | 460 | 168..169 'x': usize |
461 | 186..193 'Self::C': E | 461 | 186..193 'Self::C': E |
462 | 197..199 '{}': () | 462 | 197..199 '{}': () |
463 | "### | 463 | "#]], |
464 | ); | 464 | ); |
465 | } | 465 | } |
466 | 466 | ||
467 | #[test] | 467 | #[test] |
468 | fn infer_generics_in_patterns() { | 468 | fn infer_generics_in_patterns() { |
469 | assert_snapshot!( | 469 | check_infer( |
470 | infer(r#" | 470 | r#" |
471 | struct A<T> { | 471 | struct A<T> { |
472 | x: T, | 472 | x: T, |
473 | } | 473 | } |
474 | 474 | ||
475 | enum Option<T> { | 475 | enum Option<T> { |
476 | Some(T), | 476 | Some(T), |
477 | None, | 477 | None, |
478 | } | 478 | } |
479 | 479 | ||
480 | fn test(a1: A<u32>, o: Option<u64>) { | 480 | fn test(a1: A<u32>, o: Option<u64>) { |
481 | let A { x: x2 } = a1; | 481 | let A { x: x2 } = a1; |
482 | let A::<i64> { x: x3 } = A { x: 1 }; | 482 | let A::<i64> { x: x3 } = A { x: 1 }; |
483 | match o { | 483 | match o { |
484 | Option::Some(t) => t, | 484 | Option::Some(t) => t, |
485 | _ => 1, | 485 | _ => 1, |
486 | }; | 486 | }; |
487 | } | 487 | } |
488 | "#), | 488 | "#, |
489 | @r###" | 489 | expect![[r#" |
490 | 78..80 'a1': A<u32> | 490 | 78..80 'a1': A<u32> |
491 | 90..91 'o': Option<u64> | 491 | 90..91 'o': Option<u64> |
492 | 106..243 '{ ... }; }': () | 492 | 106..243 '{ ... }; }': () |
493 | 116..127 'A { x: x2 }': A<u32> | 493 | 116..127 'A { x: x2 }': A<u32> |
494 | 123..125 'x2': u32 | 494 | 123..125 'x2': u32 |
495 | 130..132 'a1': A<u32> | 495 | 130..132 'a1': A<u32> |
496 | 142..160 'A::<i6...: x3 }': A<i64> | 496 | 142..160 'A::<i6...: x3 }': A<i64> |
497 | 156..158 'x3': i64 | 497 | 156..158 'x3': i64 |
498 | 163..173 'A { x: 1 }': A<i64> | 498 | 163..173 'A { x: 1 }': A<i64> |
499 | 170..171 '1': i64 | 499 | 170..171 '1': i64 |
500 | 179..240 'match ... }': u64 | 500 | 179..240 'match ... }': u64 |
501 | 185..186 'o': Option<u64> | 501 | 185..186 'o': Option<u64> |
502 | 197..212 'Option::Some(t)': Option<u64> | 502 | 197..212 'Option::Some(t)': Option<u64> |
503 | 210..211 't': u64 | 503 | 210..211 't': u64 |
504 | 216..217 't': u64 | 504 | 216..217 't': u64 |
505 | 227..228 '_': Option<u64> | 505 | 227..228 '_': Option<u64> |
506 | 232..233 '1': u64 | 506 | 232..233 '1': u64 |
507 | "### | 507 | "#]], |
508 | ); | 508 | ); |
509 | } | 509 | } |
510 | 510 | ||
511 | #[test] | 511 | #[test] |
512 | fn infer_const_pattern() { | 512 | fn infer_const_pattern() { |
513 | assert_snapshot!( | 513 | check_infer_with_mismatches( |
514 | infer_with_mismatches(r#" | 514 | r#" |
515 | enum Option<T> { None } | 515 | enum Option<T> { None } |
516 | use Option::None; | 516 | use Option::None; |
517 | struct Foo; | 517 | struct Foo; |
518 | const Bar: usize = 1; | 518 | const Bar: usize = 1; |
519 | 519 | ||
520 | fn test() { | 520 | fn test() { |
521 | let a: Option<u32> = None; | 521 | let a: Option<u32> = None; |
522 | let b: Option<i64> = match a { | 522 | let b: Option<i64> = match a { |
523 | None => None, | 523 | None => None, |
524 | }; | 524 | }; |
525 | let _: () = match () { Foo => Foo }; // Expected mismatch | 525 | let _: () = match () { Foo => Foo }; // Expected mismatch |
526 | let _: () = match () { Bar => Bar }; // Expected mismatch | 526 | let _: () = match () { Bar => Bar }; // Expected mismatch |
527 | } | 527 | } |
528 | "#, true), | 528 | "#, |
529 | @r###" | 529 | expect![[r#" |
530 | 73..74 '1': usize | 530 | 73..74 '1': usize |
531 | 87..309 '{ ...atch }': () | 531 | 87..309 '{ ...atch }': () |
532 | 97..98 'a': Option<u32> | 532 | 97..98 'a': Option<u32> |
533 | 114..118 'None': Option<u32> | 533 | 114..118 'None': Option<u32> |
534 | 128..129 'b': Option<i64> | 534 | 128..129 'b': Option<i64> |
535 | 145..182 'match ... }': Option<i64> | 535 | 145..182 'match ... }': Option<i64> |
536 | 151..152 'a': Option<u32> | 536 | 151..152 'a': Option<u32> |
537 | 163..167 'None': Option<u32> | 537 | 163..167 'None': Option<u32> |
538 | 171..175 'None': Option<i64> | 538 | 171..175 'None': Option<i64> |
539 | 192..193 '_': () | 539 | 192..193 '_': () |
540 | 200..223 'match ... Foo }': Foo | 540 | 200..223 'match ... Foo }': Foo |
541 | 206..208 '()': () | 541 | 206..208 '()': () |
542 | 211..214 'Foo': Foo | 542 | 211..214 'Foo': Foo |
543 | 218..221 'Foo': Foo | 543 | 218..221 'Foo': Foo |
544 | 254..255 '_': () | 544 | 254..255 '_': () |
545 | 262..285 'match ... Bar }': usize | 545 | 262..285 'match ... Bar }': usize |
546 | 268..270 '()': () | 546 | 268..270 '()': () |
547 | 273..276 'Bar': usize | 547 | 273..276 'Bar': usize |
548 | 280..283 'Bar': usize | 548 | 280..283 'Bar': usize |
549 | 200..223: expected (), got Foo | 549 | 200..223: expected (), got Foo |
550 | 262..285: expected (), got usize | 550 | 262..285: expected (), got usize |
551 | "### | 551 | "#]], |
552 | ); | 552 | ); |
553 | } | 553 | } |
554 | 554 | ||
555 | #[test] | 555 | #[test] |
556 | fn infer_guard() { | 556 | fn infer_guard() { |
557 | assert_snapshot!( | 557 | check_infer( |
558 | infer(r#" | 558 | r#" |
559 | struct S; | 559 | struct S; |
560 | impl S { fn foo(&self) -> bool { false } } | 560 | impl S { fn foo(&self) -> bool { false } } |
561 | 561 | ||
@@ -564,91 +564,93 @@ fn main() { | |||
564 | s if s.foo() => (), | 564 | s if s.foo() => (), |
565 | } | 565 | } |
566 | } | 566 | } |
567 | "#), @r###" | 567 | "#, |
568 | 27..31 'self': &S | 568 | expect![[r#" |
569 | 41..50 '{ false }': bool | 569 | 27..31 'self': &S |
570 | 43..48 'false': bool | 570 | 41..50 '{ false }': bool |
571 | 64..115 '{ ... } }': () | 571 | 43..48 'false': bool |
572 | 70..113 'match ... }': () | 572 | 64..115 '{ ... } }': () |
573 | 76..77 'S': S | 573 | 70..113 'match ... }': () |
574 | 88..89 's': S | 574 | 76..77 'S': S |
575 | 93..94 's': S | 575 | 88..89 's': S |
576 | 93..100 's.foo()': bool | 576 | 93..94 's': S |
577 | 104..106 '()': () | 577 | 93..100 's.foo()': bool |
578 | "###) | 578 | 104..106 '()': () |
579 | "#]], | ||
580 | ) | ||
579 | } | 581 | } |
580 | 582 | ||
581 | #[test] | 583 | #[test] |
582 | fn match_ergonomics_in_closure_params() { | 584 | fn match_ergonomics_in_closure_params() { |
583 | assert_snapshot!( | 585 | check_infer( |
584 | infer(r#" | 586 | r#" |
585 | #[lang = "fn_once"] | 587 | #[lang = "fn_once"] |
586 | trait FnOnce<Args> { | 588 | trait FnOnce<Args> { |
587 | type Output; | 589 | type Output; |
588 | } | 590 | } |
589 | 591 | ||
590 | fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} } | 592 | fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} } |
591 | 593 | ||
592 | fn test() { | 594 | fn test() { |
593 | foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics | 595 | foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics |
594 | foo(&(1, "a"), |(x, y)| x); | 596 | foo(&(1, "a"), |(x, y)| x); |
595 | } | 597 | } |
596 | "#), | 598 | "#, |
597 | @r###" | 599 | expect![[r#" |
598 | 93..94 't': T | 600 | 93..94 't': T |
599 | 99..100 'f': F | 601 | 99..100 'f': F |
600 | 110..121 '{ loop {} }': U | 602 | 110..121 '{ loop {} }': U |
601 | 112..119 'loop {}': ! | 603 | 112..119 'loop {}': ! |
602 | 117..119 '{}': () | 604 | 117..119 '{}': () |
603 | 133..232 '{ ... x); }': () | 605 | 133..232 '{ ... x); }': () |
604 | 139..142 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32 | 606 | 139..142 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32 |
605 | 139..166 'foo(&(...y)| x)': i32 | 607 | 139..166 'foo(&(...y)| x)': i32 |
606 | 143..152 '&(1, "a")': &(i32, &str) | 608 | 143..152 '&(1, "a")': &(i32, &str) |
607 | 144..152 '(1, "a")': (i32, &str) | 609 | 144..152 '(1, "a")': (i32, &str) |
608 | 145..146 '1': i32 | 610 | 145..146 '1': i32 |
609 | 148..151 '"a"': &str | 611 | 148..151 '"a"': &str |
610 | 154..165 '|&(x, y)| x': |&(i32, &str)| -> i32 | 612 | 154..165 '|&(x, y)| x': |&(i32, &str)| -> i32 |
611 | 155..162 '&(x, y)': &(i32, &str) | 613 | 155..162 '&(x, y)': &(i32, &str) |
612 | 156..162 '(x, y)': (i32, &str) | 614 | 156..162 '(x, y)': (i32, &str) |
613 | 157..158 'x': i32 | 615 | 157..158 'x': i32 |
614 | 160..161 'y': &str | 616 | 160..161 'y': &str |
615 | 164..165 'x': i32 | 617 | 164..165 'x': i32 |
616 | 203..206 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32 | 618 | 203..206 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32 |
617 | 203..229 'foo(&(...y)| x)': &i32 | 619 | 203..229 'foo(&(...y)| x)': &i32 |
618 | 207..216 '&(1, "a")': &(i32, &str) | 620 | 207..216 '&(1, "a")': &(i32, &str) |
619 | 208..216 '(1, "a")': (i32, &str) | 621 | 208..216 '(1, "a")': (i32, &str) |
620 | 209..210 '1': i32 | 622 | 209..210 '1': i32 |
621 | 212..215 '"a"': &str | 623 | 212..215 '"a"': &str |
622 | 218..228 '|(x, y)| x': |&(i32, &str)| -> &i32 | 624 | 218..228 '|(x, y)| x': |&(i32, &str)| -> &i32 |
623 | 219..225 '(x, y)': (i32, &str) | 625 | 219..225 '(x, y)': (i32, &str) |
624 | 220..221 'x': &i32 | 626 | 220..221 'x': &i32 |
625 | 223..224 'y': &&str | 627 | 223..224 'y': &&str |
626 | 227..228 'x': &i32 | 628 | 227..228 'x': &i32 |
627 | "### | 629 | "#]], |
628 | ); | 630 | ); |
629 | } | 631 | } |
630 | 632 | ||
631 | #[test] | 633 | #[test] |
632 | fn slice_tail_pattern() { | 634 | fn slice_tail_pattern() { |
633 | assert_snapshot!( | 635 | check_infer( |
634 | infer(r#" | 636 | r#" |
635 | fn foo(params: &[i32]) { | 637 | fn foo(params: &[i32]) { |
636 | match params { | 638 | match params { |
637 | [head, tail @ ..] => { | 639 | [head, tail @ ..] => { |
640 | } | ||
641 | } | ||
638 | } | 642 | } |
639 | } | 643 | "#, |
640 | } | 644 | expect![[r#" |
641 | "#), | 645 | 7..13 'params': &[i32] |
642 | @r###" | 646 | 23..92 '{ ... } }': () |
643 | 7..13 'params': &[i32] | 647 | 29..90 'match ... }': () |
644 | 23..92 '{ ... } }': () | 648 | 35..41 'params': &[i32] |
645 | 29..90 'match ... }': () | 649 | 52..69 '[head,... @ ..]': [i32] |
646 | 35..41 'params': &[i32] | 650 | 53..57 'head': &i32 |
647 | 52..69 '[head,... @ ..]': [i32] | 651 | 59..68 'tail @ ..': &[i32] |
648 | 53..57 'head': &i32 | 652 | 66..68 '..': [i32] |
649 | 59..68 'tail @ ..': &[i32] | 653 | 73..84 '{ }': () |
650 | 66..68 '..': [i32] | 654 | "#]], |
651 | 73..84 '{ }': () | ||
652 | "### | ||
653 | ); | 655 | ); |
654 | } | 656 | } |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 4367621fc..b9ab0f357 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -1,87 +1,87 @@ | |||
1 | use insta::assert_snapshot; | 1 | use expect::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_types, infer}; | 4 | use super::{check_infer, check_types}; |
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn bug_484() { | 7 | fn bug_484() { |
8 | assert_snapshot!( | 8 | check_infer( |
9 | infer(r#" | 9 | r#" |
10 | fn test() { | 10 | fn test() { |
11 | let x = if true {}; | 11 | let x = if true {}; |
12 | } | 12 | } |
13 | "#), | 13 | "#, |
14 | @r###" | 14 | expect![[r#" |
15 | 10..36 '{ l... {}; }': () | 15 | 10..37 '{ ... {}; }': () |
16 | 19..20 'x': () | 16 | 20..21 'x': () |
17 | 23..33 'if true {}': () | 17 | 24..34 'if true {}': () |
18 | 26..30 'true': bool | 18 | 27..31 'true': bool |
19 | 31..33 '{}': () | 19 | 32..34 '{}': () |
20 | "### | 20 | "#]], |
21 | ); | 21 | ); |
22 | } | 22 | } |
23 | 23 | ||
24 | #[test] | 24 | #[test] |
25 | fn no_panic_on_field_of_enum() { | 25 | fn no_panic_on_field_of_enum() { |
26 | assert_snapshot!( | 26 | check_infer( |
27 | infer(r#" | 27 | r#" |
28 | enum X {} | 28 | enum X {} |
29 | 29 | ||
30 | fn test(x: X) { | 30 | fn test(x: X) { |
31 | x.some_field; | 31 | x.some_field; |
32 | } | 32 | } |
33 | "#), | 33 | "#, |
34 | @r###" | 34 | expect![[r#" |
35 | 19..20 'x': X | 35 | 19..20 'x': X |
36 | 25..46 '{ ...eld; }': () | 36 | 25..46 '{ ...eld; }': () |
37 | 31..32 'x': X | 37 | 31..32 'x': X |
38 | 31..43 'x.some_field': {unknown} | 38 | 31..43 'x.some_field': {unknown} |
39 | "### | 39 | "#]], |
40 | ); | 40 | ); |
41 | } | 41 | } |
42 | 42 | ||
43 | #[test] | 43 | #[test] |
44 | fn bug_585() { | 44 | fn bug_585() { |
45 | assert_snapshot!( | 45 | check_infer( |
46 | infer(r#" | 46 | r#" |
47 | fn test() { | 47 | fn test() { |
48 | X {}; | 48 | X {}; |
49 | match x { | 49 | match x { |
50 | A::B {} => (), | 50 | A::B {} => (), |
51 | A::Y() => (), | 51 | A::Y() => (), |
52 | } | 52 | } |
53 | } | 53 | } |
54 | "#), | 54 | "#, |
55 | @r###" | 55 | expect![[r#" |
56 | 10..88 '{ ... } }': () | 56 | 10..88 '{ ... } }': () |
57 | 16..20 'X {}': {unknown} | 57 | 16..20 'X {}': {unknown} |
58 | 26..86 'match ... }': () | 58 | 26..86 'match ... }': () |
59 | 32..33 'x': {unknown} | 59 | 32..33 'x': {unknown} |
60 | 44..51 'A::B {}': {unknown} | 60 | 44..51 'A::B {}': {unknown} |
61 | 55..57 '()': () | 61 | 55..57 '()': () |
62 | 67..73 'A::Y()': {unknown} | 62 | 67..73 'A::Y()': {unknown} |
63 | 77..79 '()': () | 63 | 77..79 '()': () |
64 | "### | 64 | "#]], |
65 | ); | 65 | ); |
66 | } | 66 | } |
67 | 67 | ||
68 | #[test] | 68 | #[test] |
69 | fn bug_651() { | 69 | fn bug_651() { |
70 | assert_snapshot!( | 70 | check_infer( |
71 | infer(r#" | 71 | r#" |
72 | fn quux() { | 72 | fn quux() { |
73 | let y = 92; | 73 | let y = 92; |
74 | 1 + y; | 74 | 1 + y; |
75 | } | 75 | } |
76 | "#), | 76 | "#, |
77 | @r###" | 77 | expect![[r#" |
78 | 10..40 '{ ...+ y; }': () | 78 | 10..40 '{ ...+ y; }': () |
79 | 20..21 'y': i32 | 79 | 20..21 'y': i32 |
80 | 24..26 '92': i32 | 80 | 24..26 '92': i32 |
81 | 32..33 '1': i32 | 81 | 32..33 '1': i32 |
82 | 32..37 '1 + y': i32 | 82 | 32..37 '1 + y': i32 |
83 | 36..37 'y': i32 | 83 | 36..37 'y': i32 |
84 | "### | 84 | "#]], |
85 | ); | 85 | ); |
86 | } | 86 | } |
87 | 87 | ||
@@ -89,78 +89,78 @@ fn quux() { | |||
89 | fn recursive_vars() { | 89 | fn recursive_vars() { |
90 | mark::check!(type_var_cycles_resolve_completely); | 90 | mark::check!(type_var_cycles_resolve_completely); |
91 | mark::check!(type_var_cycles_resolve_as_possible); | 91 | mark::check!(type_var_cycles_resolve_as_possible); |
92 | assert_snapshot!( | 92 | check_infer( |
93 | infer(r#" | 93 | r#" |
94 | fn test() { | 94 | fn test() { |
95 | let y = unknown; | 95 | let y = unknown; |
96 | [y, &y]; | 96 | [y, &y]; |
97 | } | 97 | } |
98 | "#), | 98 | "#, |
99 | @r###" | 99 | expect![[r#" |
100 | 10..47 '{ ...&y]; }': () | 100 | 10..47 '{ ...&y]; }': () |
101 | 20..21 'y': &{unknown} | 101 | 20..21 'y': &{unknown} |
102 | 24..31 'unknown': &{unknown} | 102 | 24..31 'unknown': &{unknown} |
103 | 37..44 '[y, &y]': [&&{unknown}; _] | 103 | 37..44 '[y, &y]': [&&{unknown}; _] |
104 | 38..39 'y': &{unknown} | 104 | 38..39 'y': &{unknown} |
105 | 41..43 '&y': &&{unknown} | 105 | 41..43 '&y': &&{unknown} |
106 | 42..43 'y': &{unknown} | 106 | 42..43 'y': &{unknown} |
107 | "### | 107 | "#]], |
108 | ); | 108 | ); |
109 | } | 109 | } |
110 | 110 | ||
111 | #[test] | 111 | #[test] |
112 | fn recursive_vars_2() { | 112 | fn recursive_vars_2() { |
113 | assert_snapshot!( | 113 | check_infer( |
114 | infer(r#" | 114 | r#" |
115 | fn test() { | 115 | fn test() { |
116 | let x = unknown; | 116 | let x = unknown; |
117 | let y = unknown; | 117 | let y = unknown; |
118 | [(x, y), (&y, &x)]; | 118 | [(x, y), (&y, &x)]; |
119 | } | 119 | } |
120 | "#), | 120 | "#, |
121 | @r###" | 121 | expect![[r#" |
122 | 10..79 '{ ...x)]; }': () | 122 | 10..79 '{ ...x)]; }': () |
123 | 20..21 'x': &&{unknown} | 123 | 20..21 'x': &&{unknown} |
124 | 24..31 'unknown': &&{unknown} | 124 | 24..31 'unknown': &&{unknown} |
125 | 41..42 'y': &&{unknown} | 125 | 41..42 'y': &&{unknown} |
126 | 45..52 'unknown': &&{unknown} | 126 | 45..52 'unknown': &&{unknown} |
127 | 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] | 127 | 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] |
128 | 59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) | 128 | 59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) |
129 | 60..61 'x': &&{unknown} | 129 | 60..61 'x': &&{unknown} |
130 | 63..64 'y': &&{unknown} | 130 | 63..64 'y': &&{unknown} |
131 | 67..75 '(&y, &x)': (&&&{unknown}, &&&{unknown}) | 131 | 67..75 '(&y, &x)': (&&&{unknown}, &&&{unknown}) |
132 | 68..70 '&y': &&&{unknown} | 132 | 68..70 '&y': &&&{unknown} |
133 | 69..70 'y': &&{unknown} | 133 | 69..70 'y': &&{unknown} |
134 | 72..74 '&x': &&&{unknown} | 134 | 72..74 '&x': &&&{unknown} |
135 | 73..74 'x': &&{unknown} | 135 | 73..74 'x': &&{unknown} |
136 | "### | 136 | "#]], |
137 | ); | 137 | ); |
138 | } | 138 | } |
139 | 139 | ||
140 | #[test] | 140 | #[test] |
141 | fn infer_std_crash_1() { | 141 | fn infer_std_crash_1() { |
142 | // caused stack overflow, taken from std | 142 | // caused stack overflow, taken from std |
143 | assert_snapshot!( | 143 | check_infer( |
144 | infer(r#" | 144 | r#" |
145 | enum Maybe<T> { | 145 | enum Maybe<T> { |
146 | Real(T), | 146 | Real(T), |
147 | Fake, | 147 | Fake, |
148 | } | 148 | } |
149 | 149 | ||
150 | fn write() { | 150 | fn write() { |
151 | match something_unknown { | 151 | match something_unknown { |
152 | Maybe::Real(ref mut something) => (), | 152 | Maybe::Real(ref mut something) => (), |
153 | } | 153 | } |
154 | } | 154 | } |
155 | "#), | 155 | "#, |
156 | @r###" | 156 | expect![[r#" |
157 | 53..138 '{ ... } }': () | 157 | 53..138 '{ ... } }': () |
158 | 59..136 'match ... }': () | 158 | 59..136 'match ... }': () |
159 | 65..82 'someth...nknown': Maybe<{unknown}> | 159 | 65..82 'someth...nknown': Maybe<{unknown}> |
160 | 93..123 'Maybe:...thing)': Maybe<{unknown}> | 160 | 93..123 'Maybe:...thing)': Maybe<{unknown}> |
161 | 105..122 'ref mu...ething': &mut {unknown} | 161 | 105..122 'ref mu...ething': &mut {unknown} |
162 | 127..129 '()': () | 162 | 127..129 '()': () |
163 | "### | 163 | "#]], |
164 | ); | 164 | ); |
165 | } | 165 | } |
166 | 166 | ||
@@ -168,234 +168,235 @@ fn write() { | |||
168 | fn infer_std_crash_2() { | 168 | fn infer_std_crash_2() { |
169 | mark::check!(type_var_resolves_to_int_var); | 169 | mark::check!(type_var_resolves_to_int_var); |
170 | // caused "equating two type variables, ...", taken from std | 170 | // caused "equating two type variables, ...", taken from std |
171 | assert_snapshot!( | 171 | check_infer( |
172 | infer(r#" | 172 | r#" |
173 | fn test_line_buffer() { | 173 | fn test_line_buffer() { |
174 | &[0, b'\n', 1, b'\n']; | 174 | &[0, b'\n', 1, b'\n']; |
175 | } | 175 | } |
176 | "#), | 176 | "#, |
177 | @r###" | 177 | expect![[r#" |
178 | 22..52 '{ ...n']; }': () | 178 | 22..52 '{ ...n']; }': () |
179 | 28..49 '&[0, b...b'\n']': &[u8; _] | 179 | 28..49 '&[0, b...b'\n']': &[u8; _] |
180 | 29..49 '[0, b'...b'\n']': [u8; _] | 180 | 29..49 '[0, b'...b'\n']': [u8; _] |
181 | 30..31 '0': u8 | 181 | 30..31 '0': u8 |
182 | 33..38 'b'\n'': u8 | 182 | 33..38 'b'\n'': u8 |
183 | 40..41 '1': u8 | 183 | 40..41 '1': u8 |
184 | 43..48 'b'\n'': u8 | 184 | 43..48 'b'\n'': u8 |
185 | "### | 185 | "#]], |
186 | ); | 186 | ); |
187 | } | 187 | } |
188 | 188 | ||
189 | #[test] | 189 | #[test] |
190 | fn infer_std_crash_3() { | 190 | fn infer_std_crash_3() { |
191 | // taken from rustc | 191 | // taken from rustc |
192 | assert_snapshot!( | 192 | check_infer( |
193 | infer(r#" | 193 | r#" |
194 | pub fn compute() { | 194 | pub fn compute() { |
195 | match nope!() { | 195 | match nope!() { |
196 | SizeSkeleton::Pointer { non_zero: true, tail } => {} | 196 | SizeSkeleton::Pointer { non_zero: true, tail } => {} |
197 | } | 197 | } |
198 | } | 198 | } |
199 | "#), | 199 | "#, |
200 | @r###" | 200 | expect![[r#" |
201 | 17..107 '{ ... } }': () | 201 | 17..107 '{ ... } }': () |
202 | 23..105 'match ... }': () | 202 | 23..105 'match ... }': () |
203 | 29..36 'nope!()': {unknown} | 203 | 29..36 'nope!()': {unknown} |
204 | 47..93 'SizeSk...tail }': {unknown} | 204 | 47..93 'SizeSk...tail }': {unknown} |
205 | 81..85 'true': bool | 205 | 81..85 'true': bool |
206 | 81..85 'true': bool | 206 | 81..85 'true': bool |
207 | 87..91 'tail': {unknown} | 207 | 87..91 'tail': {unknown} |
208 | 97..99 '{}': () | 208 | 97..99 '{}': () |
209 | "### | 209 | "#]], |
210 | ); | 210 | ); |
211 | } | 211 | } |
212 | 212 | ||
213 | #[test] | 213 | #[test] |
214 | fn infer_std_crash_4() { | 214 | fn infer_std_crash_4() { |
215 | // taken from rustc | 215 | // taken from rustc |
216 | assert_snapshot!( | 216 | check_infer( |
217 | infer(r#" | 217 | r#" |
218 | pub fn primitive_type() { | 218 | pub fn primitive_type() { |
219 | match *self { | 219 | match *self { |
220 | BorrowedRef { type_: Primitive(p), ..} => {}, | 220 | BorrowedRef { type_: Primitive(p), ..} => {}, |
221 | } | 221 | } |
222 | } | 222 | } |
223 | "#), | 223 | "#, |
224 | @r###" | 224 | expect![[r#" |
225 | 24..105 '{ ... } }': () | 225 | 24..105 '{ ... } }': () |
226 | 30..103 'match ... }': () | 226 | 30..103 'match ... }': () |
227 | 36..41 '*self': {unknown} | 227 | 36..41 '*self': {unknown} |
228 | 37..41 'self': {unknown} | 228 | 37..41 'self': {unknown} |
229 | 52..90 'Borrow...), ..}': {unknown} | 229 | 52..90 'Borrow...), ..}': {unknown} |
230 | 73..85 'Primitive(p)': {unknown} | 230 | 73..85 'Primitive(p)': {unknown} |
231 | 83..84 'p': {unknown} | 231 | 83..84 'p': {unknown} |
232 | 94..96 '{}': () | 232 | 94..96 '{}': () |
233 | "### | 233 | "#]], |
234 | ); | 234 | ); |
235 | } | 235 | } |
236 | 236 | ||
237 | #[test] | 237 | #[test] |
238 | fn infer_std_crash_5() { | 238 | fn infer_std_crash_5() { |
239 | // taken from rustc | 239 | // taken from rustc |
240 | assert_snapshot!( | 240 | check_infer( |
241 | infer(r#" | 241 | r#" |
242 | fn extra_compiler_flags() { | 242 | fn extra_compiler_flags() { |
243 | for content in doesnt_matter { | 243 | for content in doesnt_matter { |
244 | let name = if doesnt_matter { | 244 | let name = if doesnt_matter { |
245 | first | 245 | first |
246 | } else { | 246 | } else { |
247 | &content | 247 | &content |
248 | }; | 248 | }; |
249 | 249 | ||
250 | let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { | 250 | let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { |
251 | name | 251 | name |
252 | } else { | 252 | } else { |
253 | content | 253 | content |
254 | }; | 254 | }; |
255 | } | 255 | } |
256 | } | 256 | } |
257 | "#), | 257 | "#, |
258 | @r###" | 258 | expect![[r#" |
259 | 26..322 '{ ... } }': () | 259 | 26..322 '{ ... } }': () |
260 | 32..320 'for co... }': () | 260 | 32..320 'for co... }': () |
261 | 36..43 'content': &{unknown} | 261 | 36..43 'content': &{unknown} |
262 | 47..60 'doesnt_matter': {unknown} | 262 | 47..60 'doesnt_matter': {unknown} |
263 | 61..320 '{ ... }': () | 263 | 61..320 '{ ... }': () |
264 | 75..79 'name': &&{unknown} | 264 | 75..79 'name': &&{unknown} |
265 | 82..166 'if doe... }': &&{unknown} | 265 | 82..166 'if doe... }': &&{unknown} |
266 | 85..98 'doesnt_matter': bool | 266 | 85..98 'doesnt_matter': bool |
267 | 99..128 '{ ... }': &&{unknown} | 267 | 99..128 '{ ... }': &&{unknown} |
268 | 113..118 'first': &&{unknown} | 268 | 113..118 'first': &&{unknown} |
269 | 134..166 '{ ... }': &&{unknown} | 269 | 134..166 '{ ... }': &&{unknown} |
270 | 148..156 '&content': &&{unknown} | 270 | 148..156 '&content': &&{unknown} |
271 | 149..156 'content': &{unknown} | 271 | 149..156 'content': &{unknown} |
272 | 181..188 'content': &{unknown} | 272 | 181..188 'content': &{unknown} |
273 | 191..313 'if ICE... }': &{unknown} | 273 | 191..313 'if ICE... }': &{unknown} |
274 | 194..231 'ICE_RE..._VALUE': {unknown} | 274 | 194..231 'ICE_RE..._VALUE': {unknown} |
275 | 194..247 'ICE_RE...&name)': bool | 275 | 194..247 'ICE_RE...&name)': bool |
276 | 241..246 '&name': &&&{unknown} | 276 | 241..246 '&name': &&&{unknown} |
277 | 242..246 'name': &&{unknown} | 277 | 242..246 'name': &&{unknown} |
278 | 248..276 '{ ... }': &&{unknown} | 278 | 248..276 '{ ... }': &&{unknown} |
279 | 262..266 'name': &&{unknown} | 279 | 262..266 'name': &&{unknown} |
280 | 282..313 '{ ... }': &{unknown} | 280 | 282..313 '{ ... }': &{unknown} |
281 | 296..303 'content': &{unknown} | 281 | 296..303 'content': &{unknown} |
282 | "### | 282 | "#]], |
283 | ); | 283 | ); |
284 | } | 284 | } |
285 | 285 | ||
286 | #[test] | 286 | #[test] |
287 | fn infer_nested_generics_crash() { | 287 | fn infer_nested_generics_crash() { |
288 | // another crash found typechecking rustc | 288 | // another crash found typechecking rustc |
289 | assert_snapshot!( | 289 | check_infer( |
290 | infer(r#" | 290 | r#" |
291 | struct Canonical<V> { | 291 | struct Canonical<V> { |
292 | value: V, | 292 | value: V, |
293 | } | 293 | } |
294 | struct QueryResponse<V> { | 294 | struct QueryResponse<V> { |
295 | value: V, | 295 | value: V, |
296 | } | 296 | } |
297 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { | 297 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { |
298 | &query_response.value; | 298 | &query_response.value; |
299 | } | 299 | } |
300 | "#), | 300 | "#, |
301 | @r###" | 301 | expect![[r#" |
302 | 91..105 'query_response': Canonical<QueryResponse<R>> | 302 | 91..105 'query_response': Canonical<QueryResponse<R>> |
303 | 136..166 '{ ...lue; }': () | 303 | 136..166 '{ ...lue; }': () |
304 | 142..163 '&query....value': &QueryResponse<R> | 304 | 142..163 '&query....value': &QueryResponse<R> |
305 | 143..157 'query_response': Canonical<QueryResponse<R>> | 305 | 143..157 'query_response': Canonical<QueryResponse<R>> |
306 | 143..163 'query_....value': QueryResponse<R> | 306 | 143..163 'query_....value': QueryResponse<R> |
307 | "### | 307 | "#]], |
308 | ); | 308 | ); |
309 | } | 309 | } |
310 | 310 | ||
311 | #[test] | 311 | #[test] |
312 | fn infer_paren_macro_call() { | 312 | fn infer_paren_macro_call() { |
313 | assert_snapshot!( | 313 | check_infer( |
314 | infer(r#" | 314 | r#" |
315 | macro_rules! bar { () => {0u32} } | 315 | macro_rules! bar { () => {0u32} } |
316 | fn test() { | 316 | fn test() { |
317 | let a = (bar!()); | 317 | let a = (bar!()); |
318 | } | 318 | } |
319 | "#), | 319 | "#, |
320 | @r###" | 320 | expect![[r#" |
321 | !0..4 '0u32': u32 | 321 | !0..4 '0u32': u32 |
322 | 44..69 '{ ...()); }': () | 322 | 44..69 '{ ...()); }': () |
323 | 54..55 'a': u32 | 323 | 54..55 'a': u32 |
324 | "### | 324 | "#]], |
325 | ); | 325 | ); |
326 | } | 326 | } |
327 | 327 | ||
328 | #[test] | 328 | #[test] |
329 | fn bug_1030() { | 329 | fn bug_1030() { |
330 | assert_snapshot!(infer(r#" | 330 | check_infer( |
331 | struct HashSet<T, H>; | 331 | r#" |
332 | struct FxHasher; | 332 | struct HashSet<T, H>; |
333 | type FxHashSet<T> = HashSet<T, FxHasher>; | 333 | struct FxHasher; |
334 | type FxHashSet<T> = HashSet<T, FxHasher>; | ||
334 | 335 | ||
335 | impl<T, H> HashSet<T, H> { | 336 | impl<T, H> HashSet<T, H> { |
336 | fn default() -> HashSet<T, H> {} | 337 | fn default() -> HashSet<T, H> {} |
337 | } | 338 | } |
338 | 339 | ||
339 | pub fn main_loop() { | 340 | pub fn main_loop() { |
340 | FxHashSet::default(); | 341 | FxHashSet::default(); |
341 | } | 342 | } |
342 | "#), | 343 | "#, |
343 | @r###" | 344 | expect![[r#" |
344 | 143..145 '{}': () | 345 | 143..145 '{}': () |
345 | 168..197 '{ ...t(); }': () | 346 | 168..197 '{ ...t(); }': () |
346 | 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> | 347 | 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> |
347 | 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> | 348 | 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> |
348 | "### | 349 | "#]], |
349 | ); | 350 | ); |
350 | } | 351 | } |
351 | 352 | ||
352 | #[test] | 353 | #[test] |
353 | fn issue_2669() { | 354 | fn issue_2669() { |
354 | assert_snapshot!( | 355 | check_infer( |
355 | infer( | 356 | r#" |
356 | r#"trait A {} | 357 | trait A {} |
357 | trait Write {} | 358 | trait Write {} |
358 | struct Response<T> {} | 359 | struct Response<T> {} |
359 | 360 | ||
360 | trait D { | 361 | trait D { |
361 | fn foo(); | 362 | fn foo(); |
362 | } | 363 | } |
363 | 364 | ||
364 | impl<T:A> D for Response<T> { | 365 | impl<T:A> D for Response<T> { |
365 | fn foo() { | 366 | fn foo() { |
366 | end(); | 367 | end(); |
367 | fn end<W: Write>() { | 368 | fn end<W: Write>() { |
368 | let _x: T = loop {}; | 369 | let _x: T = loop {}; |
370 | } | ||
369 | } | 371 | } |
370 | } | 372 | } |
371 | }"# | 373 | "#, |
372 | ), | 374 | expect![[r#" |
373 | @r###" | 375 | 119..214 '{ ... }': () |
374 | 147..262 '{ ... }': () | 376 | 129..132 'end': fn end<{unknown}>() |
375 | 161..164 'end': fn end<{unknown}>() | 377 | 129..134 'end()': () |
376 | 161..166 'end()': () | 378 | 163..208 '{ ... }': () |
377 | 199..252 '{ ... }': () | 379 | 181..183 '_x': ! |
378 | 221..223 '_x': ! | 380 | 190..197 'loop {}': ! |
379 | 230..237 'loop {}': ! | 381 | 195..197 '{}': () |
380 | 235..237 '{}': () | 382 | "#]], |
381 | "### | ||
382 | ) | 383 | ) |
383 | } | 384 | } |
384 | 385 | ||
385 | #[test] | 386 | #[test] |
386 | fn issue_2705() { | 387 | fn issue_2705() { |
387 | assert_snapshot!( | 388 | check_infer( |
388 | infer(r#" | 389 | r#" |
389 | trait Trait {} | 390 | trait Trait {} |
390 | fn test() { | 391 | fn test() { |
391 | <Trait<u32>>::foo() | 392 | <Trait<u32>>::foo() |
392 | } | 393 | } |
393 | "#), | 394 | "#, |
394 | @r###" | 395 | expect![[r#" |
395 | 25..52 '{ ...oo() }': () | 396 | 25..52 '{ ...oo() }': () |
396 | 31..48 '<Trait...>::foo': {unknown} | 397 | 31..48 '<Trait...>::foo': {unknown} |
397 | 31..50 '<Trait...:foo()': () | 398 | 31..50 '<Trait...:foo()': () |
398 | "### | 399 | "#]], |
399 | ); | 400 | ); |
400 | } | 401 | } |
401 | 402 | ||
@@ -479,25 +480,25 @@ fn main() { | |||
479 | 480 | ||
480 | #[test] | 481 | #[test] |
481 | fn issue_3999_slice() { | 482 | fn issue_3999_slice() { |
482 | assert_snapshot!( | 483 | check_infer( |
483 | infer(r#" | 484 | r#" |
484 | fn foo(params: &[usize]) { | 485 | fn foo(params: &[usize]) { |
485 | match params { | 486 | match params { |
486 | [ps @ .., _] => {} | 487 | [ps @ .., _] => {} |
487 | } | 488 | } |
488 | } | 489 | } |
489 | "#), | 490 | "#, |
490 | @r###" | 491 | expect![[r#" |
491 | 7..13 'params': &[usize] | 492 | 7..13 'params': &[usize] |
492 | 25..80 '{ ... } }': () | 493 | 25..80 '{ ... } }': () |
493 | 31..78 'match ... }': () | 494 | 31..78 'match ... }': () |
494 | 37..43 'params': &[usize] | 495 | 37..43 'params': &[usize] |
495 | 54..66 '[ps @ .., _]': [usize] | 496 | 54..66 '[ps @ .., _]': [usize] |
496 | 55..62 'ps @ ..': &[usize] | 497 | 55..62 'ps @ ..': &[usize] |
497 | 60..62 '..': [usize] | 498 | 60..62 '..': [usize] |
498 | 64..65 '_': usize | 499 | 64..65 '_': usize |
499 | 70..72 '{}': () | 500 | 70..72 '{}': () |
500 | "### | 501 | "#]], |
501 | ); | 502 | ); |
502 | } | 503 | } |
503 | 504 | ||
@@ -505,334 +506,337 @@ fn foo(params: &[usize]) { | |||
505 | fn issue_3999_struct() { | 506 | fn issue_3999_struct() { |
506 | // rust-analyzer should not panic on seeing this malformed | 507 | // rust-analyzer should not panic on seeing this malformed |
507 | // record pattern. | 508 | // record pattern. |
508 | assert_snapshot!( | 509 | check_infer( |
509 | infer(r#" | 510 | r#" |
510 | struct Bar { | 511 | struct Bar { |
511 | a: bool, | 512 | a: bool, |
512 | } | 513 | } |
513 | fn foo(b: Bar) { | 514 | fn foo(b: Bar) { |
514 | match b { | 515 | match b { |
515 | Bar { a: .. } => {}, | 516 | Bar { a: .. } => {}, |
516 | } | 517 | } |
517 | } | 518 | } |
518 | "#), | 519 | "#, |
519 | @r###" | 520 | expect![[r#" |
520 | 35..36 'b': Bar | 521 | 35..36 'b': Bar |
521 | 43..95 '{ ... } }': () | 522 | 43..95 '{ ... } }': () |
522 | 49..93 'match ... }': () | 523 | 49..93 'match ... }': () |
523 | 55..56 'b': Bar | 524 | 55..56 'b': Bar |
524 | 67..80 'Bar { a: .. }': Bar | 525 | 67..80 'Bar { a: .. }': Bar |
525 | 76..78 '..': bool | 526 | 76..78 '..': bool |
526 | 84..86 '{}': () | 527 | 84..86 '{}': () |
527 | "### | 528 | "#]], |
528 | ); | 529 | ); |
529 | } | 530 | } |
530 | 531 | ||
531 | #[test] | 532 | #[test] |
532 | fn issue_4235_name_conflicts() { | 533 | fn issue_4235_name_conflicts() { |
533 | assert_snapshot!( | 534 | check_infer( |
534 | infer(r#" | 535 | r#" |
535 | struct FOO {} | 536 | struct FOO {} |
536 | static FOO:FOO = FOO {}; | 537 | static FOO:FOO = FOO {}; |
537 | 538 | ||
538 | impl FOO { | 539 | impl FOO { |
539 | fn foo(&self) {} | 540 | fn foo(&self) {} |
540 | } | 541 | } |
541 | 542 | ||
542 | fn main() { | 543 | fn main() { |
543 | let a = &FOO; | 544 | let a = &FOO; |
544 | a.foo(); | 545 | a.foo(); |
545 | } | 546 | } |
546 | "#), @r###" | 547 | "#, |
547 | 31..37 'FOO {}': FOO | 548 | expect![[r#" |
548 | 63..67 'self': &FOO | 549 | 31..37 'FOO {}': FOO |
549 | 69..71 '{}': () | 550 | 63..67 'self': &FOO |
550 | 85..119 '{ ...o(); }': () | 551 | 69..71 '{}': () |
551 | 95..96 'a': &FOO | 552 | 85..119 '{ ...o(); }': () |
552 | 99..103 '&FOO': &FOO | 553 | 95..96 'a': &FOO |
553 | 100..103 'FOO': FOO | 554 | 99..103 '&FOO': &FOO |
554 | 109..110 'a': &FOO | 555 | 100..103 'FOO': FOO |
555 | 109..116 'a.foo()': () | 556 | 109..110 'a': &FOO |
556 | "### | 557 | 109..116 'a.foo()': () |
558 | "#]], | ||
557 | ); | 559 | ); |
558 | } | 560 | } |
559 | 561 | ||
560 | #[test] | 562 | #[test] |
561 | fn issue_4465_dollar_crate_at_type() { | 563 | fn issue_4465_dollar_crate_at_type() { |
562 | assert_snapshot!( | 564 | check_infer( |
563 | infer(r#" | 565 | r#" |
564 | pub struct Foo {} | 566 | pub struct Foo {} |
565 | pub fn anything<T>() -> T { | 567 | pub fn anything<T>() -> T { |
566 | loop {} | 568 | loop {} |
567 | } | 569 | } |
568 | macro_rules! foo { | 570 | macro_rules! foo { |
569 | () => {{ | 571 | () => {{ |
570 | let r: $crate::Foo = anything(); | 572 | let r: $crate::Foo = anything(); |
571 | r | 573 | r |
572 | }}; | 574 | }}; |
573 | } | 575 | } |
574 | fn main() { | 576 | fn main() { |
575 | let _a = foo!(); | 577 | let _a = foo!(); |
576 | } | 578 | } |
577 | "#), @r###" | 579 | "#, |
578 | 44..59 '{ loop {} }': T | 580 | expect![[r#" |
579 | 50..57 'loop {}': ! | 581 | 44..59 '{ loop {} }': T |
580 | 55..57 '{}': () | 582 | 50..57 'loop {}': ! |
581 | !0..31 '{letr:...g();r}': Foo | 583 | 55..57 '{}': () |
582 | !4..5 'r': Foo | 584 | !0..31 '{letr:...g();r}': Foo |
583 | !18..26 'anything': fn anything<Foo>() -> Foo | 585 | !4..5 'r': Foo |
584 | !18..28 'anything()': Foo | 586 | !18..26 'anything': fn anything<Foo>() -> Foo |
585 | !29..30 'r': Foo | 587 | !18..28 'anything()': Foo |
586 | 163..187 '{ ...!(); }': () | 588 | !29..30 'r': Foo |
587 | 173..175 '_a': Foo | 589 | 163..187 '{ ...!(); }': () |
588 | "###); | 590 | 173..175 '_a': Foo |
591 | "#]], | ||
592 | ); | ||
589 | } | 593 | } |
590 | 594 | ||
591 | #[test] | 595 | #[test] |
592 | fn issue_4053_diesel_where_clauses() { | 596 | fn issue_4053_diesel_where_clauses() { |
593 | assert_snapshot!( | 597 | check_infer( |
594 | infer(r#" | 598 | r#" |
595 | trait BoxedDsl<DB> { | 599 | trait BoxedDsl<DB> { |
596 | type Output; | 600 | type Output; |
597 | fn internal_into_boxed(self) -> Self::Output; | 601 | fn internal_into_boxed(self) -> Self::Output; |
598 | } | 602 | } |
599 | 603 | ||
600 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | 604 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { |
601 | order: Order, | 605 | order: Order, |
602 | } | 606 | } |
603 | 607 | ||
604 | trait QueryFragment<DB: Backend> {} | 608 | trait QueryFragment<DB: Backend> {} |
605 | 609 | ||
606 | trait Into<T> { fn into(self) -> T; } | 610 | trait Into<T> { fn into(self) -> T; } |
607 | 611 | ||
608 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | 612 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> |
609 | for SelectStatement<F, S, D, W, O, LOf, G> | 613 | for SelectStatement<F, S, D, W, O, LOf, G> |
610 | where | 614 | where |
611 | O: Into<dyn QueryFragment<DB>>, | 615 | O: Into<dyn QueryFragment<DB>>, |
612 | { | 616 | { |
613 | type Output = XXX; | 617 | type Output = XXX; |
614 | 618 | ||
615 | fn internal_into_boxed(self) -> Self::Output { | 619 | fn internal_into_boxed(self) -> Self::Output { |
616 | self.order.into(); | 620 | self.order.into(); |
617 | } | 621 | } |
618 | } | 622 | } |
619 | "#), | 623 | "#, |
620 | @r###" | 624 | expect![[r#" |
621 | 65..69 'self': Self | 625 | 65..69 'self': Self |
622 | 267..271 'self': Self | 626 | 267..271 'self': Self |
623 | 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | 627 | 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> |
624 | 488..522 '{ ... }': () | 628 | 488..522 '{ ... }': () |
625 | 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | 629 | 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> |
626 | 498..508 'self.order': O | 630 | 498..508 'self.order': O |
627 | 498..515 'self.o...into()': dyn QueryFragment<DB> | 631 | 498..515 'self.o...into()': dyn QueryFragment<DB> |
628 | "### | 632 | "#]], |
629 | ); | 633 | ); |
630 | } | 634 | } |
631 | 635 | ||
632 | #[test] | 636 | #[test] |
633 | fn issue_4953() { | 637 | fn issue_4953() { |
634 | assert_snapshot!( | 638 | check_infer( |
635 | infer(r#" | 639 | r#" |
636 | pub struct Foo(pub i64); | 640 | pub struct Foo(pub i64); |
637 | impl Foo { | 641 | impl Foo { |
638 | fn test() -> Self { Self(0i64) } | 642 | fn test() -> Self { Self(0i64) } |
639 | } | 643 | } |
640 | "#), | 644 | "#, |
641 | @r###" | 645 | expect![[r#" |
642 | 58..72 '{ Self(0i64) }': Foo | 646 | 58..72 '{ Self(0i64) }': Foo |
643 | 60..64 'Self': Foo(i64) -> Foo | 647 | 60..64 'Self': Foo(i64) -> Foo |
644 | 60..70 'Self(0i64)': Foo | 648 | 60..70 'Self(0i64)': Foo |
645 | 65..69 '0i64': i64 | 649 | 65..69 '0i64': i64 |
646 | "### | 650 | "#]], |
647 | ); | 651 | ); |
648 | assert_snapshot!( | 652 | check_infer( |
649 | infer(r#" | 653 | r#" |
650 | pub struct Foo<T>(pub T); | 654 | pub struct Foo<T>(pub T); |
651 | impl Foo<i64> { | 655 | impl Foo<i64> { |
652 | fn test() -> Self { Self(0i64) } | 656 | fn test() -> Self { Self(0i64) } |
653 | } | 657 | } |
654 | "#), | 658 | "#, |
655 | @r###" | 659 | expect![[r#" |
656 | 64..78 '{ Self(0i64) }': Foo<i64> | 660 | 64..78 '{ Self(0i64) }': Foo<i64> |
657 | 66..70 'Self': Foo<i64>(i64) -> Foo<i64> | 661 | 66..70 'Self': Foo<i64>(i64) -> Foo<i64> |
658 | 66..76 'Self(0i64)': Foo<i64> | 662 | 66..76 'Self(0i64)': Foo<i64> |
659 | 71..75 '0i64': i64 | 663 | 71..75 '0i64': i64 |
660 | "### | 664 | "#]], |
661 | ); | 665 | ); |
662 | } | 666 | } |
663 | 667 | ||
664 | #[test] | 668 | #[test] |
665 | fn issue_4931() { | 669 | fn issue_4931() { |
666 | assert_snapshot!( | 670 | check_infer( |
667 | infer(r#" | 671 | r#" |
668 | trait Div<T> { | 672 | trait Div<T> { |
669 | type Output; | 673 | type Output; |
670 | } | 674 | } |
671 | 675 | ||
672 | trait CheckedDiv: Div<()> {} | 676 | trait CheckedDiv: Div<()> {} |
673 | 677 | ||
674 | trait PrimInt: CheckedDiv<Output = ()> { | 678 | trait PrimInt: CheckedDiv<Output = ()> { |
675 | fn pow(self); | 679 | fn pow(self); |
676 | } | 680 | } |
677 | 681 | ||
678 | fn check<T: PrimInt>(i: T) { | 682 | fn check<T: PrimInt>(i: T) { |
679 | i.pow(); | 683 | i.pow(); |
680 | } | 684 | } |
681 | "#), | 685 | "#, |
682 | @r###" | 686 | expect![[r#" |
683 | 117..121 'self': Self | 687 | 117..121 'self': Self |
684 | 148..149 'i': T | 688 | 148..149 'i': T |
685 | 154..170 '{ ...w(); }': () | 689 | 154..170 '{ ...w(); }': () |
686 | 160..161 'i': T | 690 | 160..161 'i': T |
687 | 160..167 'i.pow()': () | 691 | 160..167 'i.pow()': () |
688 | "### | 692 | "#]], |
689 | ); | 693 | ); |
690 | } | 694 | } |
691 | 695 | ||
692 | #[test] | 696 | #[test] |
693 | fn issue_4885() { | 697 | fn issue_4885() { |
694 | assert_snapshot!( | 698 | check_infer( |
695 | infer(r#" | 699 | r#" |
696 | #[lang = "coerce_unsized"] | 700 | #[lang = "coerce_unsized"] |
697 | pub trait CoerceUnsized<T> {} | 701 | pub trait CoerceUnsized<T> {} |
698 | 702 | ||
699 | trait Future { | 703 | trait Future { |
700 | type Output; | 704 | type Output; |
701 | } | 705 | } |
702 | trait Foo<R> { | 706 | trait Foo<R> { |
703 | type Bar; | 707 | type Bar; |
704 | } | 708 | } |
705 | fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> | 709 | fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> |
706 | where | 710 | where |
707 | K: Foo<R>, | 711 | K: Foo<R>, |
708 | { | 712 | { |
709 | bar(key) | 713 | bar(key) |
710 | } | 714 | } |
711 | fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> | 715 | fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> |
712 | where | 716 | where |
713 | K: Foo<R>, | 717 | K: Foo<R>, |
714 | { | 718 | { |
715 | } | 719 | } |
716 | "#), | 720 | "#, |
717 | @r###" | 721 | expect![[r#" |
718 | 136..139 'key': &K | 722 | 136..139 'key': &K |
719 | 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> | 723 | 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> |
720 | 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> | 724 | 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> |
721 | 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> | 725 | 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> |
722 | 208..211 'key': &K | 726 | 208..211 'key': &K |
723 | 228..231 'key': &K | 727 | 228..231 'key': &K |
724 | 290..293 '{ }': () | 728 | 290..293 '{ }': () |
725 | "### | 729 | "#]], |
726 | ); | 730 | ); |
727 | } | 731 | } |
728 | 732 | ||
729 | #[test] | 733 | #[test] |
730 | fn issue_4800() { | 734 | fn issue_4800() { |
731 | assert_snapshot!( | 735 | check_infer( |
732 | infer(r#" | 736 | r#" |
733 | trait Debug {} | 737 | trait Debug {} |
734 | 738 | ||
735 | struct Foo<T>; | 739 | struct Foo<T>; |
736 | 740 | ||
737 | type E1<T> = (T, T, T); | 741 | type E1<T> = (T, T, T); |
738 | type E2<T> = E1<E1<E1<(T, T, T)>>>; | 742 | type E2<T> = E1<E1<E1<(T, T, T)>>>; |
739 | 743 | ||
740 | impl Debug for Foo<E2<()>> {} | 744 | impl Debug for Foo<E2<()>> {} |
741 | 745 | ||
742 | struct Request; | 746 | struct Request; |
743 | 747 | ||
744 | pub trait Future { | 748 | pub trait Future { |
745 | type Output; | 749 | type Output; |
746 | } | 750 | } |
747 | 751 | ||
748 | pub struct PeerSet<D>; | 752 | pub struct PeerSet<D>; |
749 | 753 | ||
750 | impl<D> Service<Request> for PeerSet<D> | 754 | impl<D> Service<Request> for PeerSet<D> |
751 | where | 755 | where |
752 | D: Discover, | 756 | D: Discover, |
753 | D::Key: Debug, | 757 | D::Key: Debug, |
754 | { | 758 | { |
755 | type Error = (); | 759 | type Error = (); |
756 | type Future = dyn Future<Output = Self::Error>; | 760 | type Future = dyn Future<Output = Self::Error>; |
757 | 761 | ||
758 | fn call(&mut self) -> Self::Future { | 762 | fn call(&mut self) -> Self::Future { |
759 | loop {} | 763 | loop {} |
760 | } | 764 | } |
761 | } | 765 | } |
762 | 766 | ||
763 | pub trait Discover { | 767 | pub trait Discover { |
764 | type Key; | 768 | type Key; |
765 | } | 769 | } |
766 | 770 | ||
767 | pub trait Service<Request> { | 771 | pub trait Service<Request> { |
768 | type Error; | 772 | type Error; |
769 | type Future: Future<Output = Self::Error>; | 773 | type Future: Future<Output = Self::Error>; |
770 | fn call(&mut self) -> Self::Future; | 774 | fn call(&mut self) -> Self::Future; |
771 | } | 775 | } |
772 | "#), | 776 | "#, |
773 | @r###" | 777 | expect![[r#" |
774 | 379..383 'self': &mut PeerSet<D> | 778 | 379..383 'self': &mut PeerSet<D> |
775 | 401..424 '{ ... }': dyn Future<Output = ()> | 779 | 401..424 '{ ... }': dyn Future<Output = ()> |
776 | 411..418 'loop {}': ! | 780 | 411..418 'loop {}': ! |
777 | 416..418 '{}': () | 781 | 416..418 '{}': () |
778 | 575..579 'self': &mut Self | 782 | 575..579 'self': &mut Self |
779 | "### | 783 | "#]], |
780 | ); | 784 | ); |
781 | } | 785 | } |
782 | 786 | ||
783 | #[test] | 787 | #[test] |
784 | fn issue_4966() { | 788 | fn issue_4966() { |
785 | assert_snapshot!( | 789 | check_infer( |
786 | infer(r#" | 790 | r#" |
787 | pub trait IntoIterator { | 791 | pub trait IntoIterator { |
788 | type Item; | 792 | type Item; |
789 | } | 793 | } |
790 | 794 | ||
791 | struct Repeat<A> { element: A } | 795 | struct Repeat<A> { element: A } |
792 | 796 | ||
793 | struct Map<F> { f: F } | 797 | struct Map<F> { f: F } |
794 | 798 | ||
795 | struct Vec<T> {} | 799 | struct Vec<T> {} |
796 | 800 | ||
797 | #[lang = "deref"] | 801 | #[lang = "deref"] |
798 | pub trait Deref { | 802 | pub trait Deref { |
799 | type Target; | 803 | type Target; |
800 | } | 804 | } |
801 | 805 | ||
802 | impl<T> Deref for Vec<T> { | 806 | impl<T> Deref for Vec<T> { |
803 | type Target = [T]; | 807 | type Target = [T]; |
804 | } | 808 | } |
805 | 809 | ||
806 | fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} | 810 | fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} |
807 | 811 | ||
808 | fn main() { | 812 | fn main() { |
809 | let inner = Map { f: |_: &f64| 0.0 }; | 813 | let inner = Map { f: |_: &f64| 0.0 }; |
810 | 814 | ||
811 | let repeat = Repeat { element: inner }; | 815 | let repeat = Repeat { element: inner }; |
812 | 816 | ||
813 | let vec = from_iter(repeat); | 817 | let vec = from_iter(repeat); |
814 | 818 | ||
815 | vec.foo_bar(); | 819 | vec.foo_bar(); |
816 | } | 820 | } |
817 | "#), | 821 | "#, |
818 | @r###" | 822 | expect![[r#" |
819 | 270..274 'iter': T | 823 | 270..274 'iter': T |
820 | 289..291 '{}': () | 824 | 289..291 '{}': () |
821 | 303..447 '{ ...r(); }': () | 825 | 303..447 '{ ...r(); }': () |
822 | 313..318 'inner': Map<|&f64| -> f64> | 826 | 313..318 'inner': Map<|&f64| -> f64> |
823 | 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> | 827 | 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> |
824 | 330..343 '|_: &f64| 0.0': |&f64| -> f64 | 828 | 330..343 '|_: &f64| 0.0': |&f64| -> f64 |
825 | 331..332 '_': &f64 | 829 | 331..332 '_': &f64 |
826 | 340..343 '0.0': f64 | 830 | 340..343 '0.0': f64 |
827 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> | 831 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> |
828 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> | 832 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> |
829 | 383..388 'inner': Map<|&f64| -> f64> | 833 | 383..388 'inner': Map<|&f64| -> f64> |
830 | 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | 834 | 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
831 | 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | 835 | 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
832 | 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | 836 | 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
833 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> | 837 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> |
834 | 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | 838 | 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
835 | 431..444 'vec.foo_bar()': {unknown} | 839 | 431..444 'vec.foo_bar()': {unknown} |
836 | "### | 840 | "#]], |
837 | ); | 841 | ); |
838 | } | 842 | } |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 6d3e264af..3fd7d5cd4 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use insta::assert_snapshot; | 1 | use expect::expect; |
2 | 2 | ||
3 | use super::{check_types, infer}; | 3 | use super::{check_infer, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn infer_box() { | 6 | fn infer_box() { |
@@ -45,43 +45,44 @@ fn test() { | |||
45 | 45 | ||
46 | #[test] | 46 | #[test] |
47 | fn self_in_struct_lit() { | 47 | fn self_in_struct_lit() { |
48 | assert_snapshot!(infer( | 48 | check_infer( |
49 | r#" |