aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock133
-rw-r--r--crates/paths/src/lib.rs5
-rw-r--r--crates/ra_assists/src/assist_context.rs2
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs280
-rw-r--r--crates/ra_assists/src/utils.rs2
-rw-r--r--crates/ra_assists/src/utils/insert_use.rs24
-rw-r--r--crates/ra_db/src/input.rs35
-rw-r--r--crates/ra_hir/src/code_model.rs115
-rw-r--r--crates/ra_hir/src/db.rs2
-rw-r--r--crates/ra_hir/src/semantics.rs15
-rw-r--r--crates/ra_hir/src/source_analyzer.rs10
-rw-r--r--crates/ra_hir_def/src/body/scope.rs34
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs3
-rw-r--r--crates/ra_hir_def/src/lib.rs2
-rw-r--r--crates/ra_hir_def/src/nameres.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs7
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs8
-rw-r--r--crates/ra_hir_ty/src/_match.rs857
-rw-r--r--crates/ra_hir_ty/src/db.rs15
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs12
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs81
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs2
-rw-r--r--crates/ra_hir_ty/src/lib.rs63
-rw-r--r--crates/ra_hir_ty/src/lower.rs25
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs69
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs151
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs223
-rw-r--r--crates/ra_hir_ty/src/traits.rs43
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs20
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs28
-rw-r--r--crates/ra_hir_ty/src/utils.rs14
-rw-r--r--crates/ra_ide/Cargo.toml1
-rw-r--r--crates/ra_ide/src/diagnostics.rs118
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs23
-rw-r--r--crates/ra_ide/src/hover.rs1142
-rw-r--r--crates/ra_ide/src/lib.rs12
-rw-r--r--crates/ra_ide/src/prime_caches.rs2
-rw-r--r--crates/ra_ide/src/references/rename.rs266
-rw-r--r--crates/ra_ide/src/runnables.rs18
-rw-r--r--crates/ra_ide/src/snapshots/highlight_doctest.html91
-rw-r--r--crates/ra_ide/src/snapshots/highlight_injection.html2
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html8
-rw-r--r--crates/ra_ide/src/snapshots/highlight_unsafe.html2
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html2
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html2
-rw-r--r--crates/ra_ide/src/ssr.rs601
-rw-r--r--crates/ra_ide/src/status.rs15
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs97
-rw-r--r--crates/ra_ide/src/syntax_highlighting/html.rs4
-rw-r--r--crates/ra_ide/src/syntax_highlighting/injection.rs24
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs5
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs33
-rw-r--r--crates/ra_ide_db/src/change.rs81
-rw-r--r--crates/ra_ide_db/src/source_change.rs6
-rw-r--r--crates/ra_ide_db/src/symbol_index.rs90
-rw-r--r--crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt2
-rw-r--r--crates/ra_ssr/Cargo.toml19
-rw-r--r--crates/ra_ssr/src/lib.rs120
-rw-r--r--crates/ra_ssr/src/matching.rs494
-rw-r--r--crates/ra_ssr/src/parsing.rs272
-rw-r--r--crates/ra_ssr/src/replacing.rs55
-rw-r--r--crates/ra_ssr/src/tests.rs496
-rw-r--r--crates/ra_syntax/src/algo.rs8
-rw-r--r--crates/ra_syntax/src/ast/make.rs4
-rw-r--r--crates/ra_syntax/src/lib.rs35
-rw-r--r--crates/ra_syntax/src/parsing.rs32
-rw-r--r--crates/ra_syntax/src/parsing/text_token_source.rs89
-rw-r--r--crates/ra_syntax/src/tests.rs66
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast22
-rw-r--r--crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs1
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/build.rs5
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs32
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs6
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap86
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap86
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs213
-rw-r--r--crates/rust-analyzer/src/global_state.rs96
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/main_loop.rs241
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs48
-rw-r--r--crates/rust-analyzer/src/main_loop/pending_requests.rs75
-rw-r--r--crates/rust-analyzer/src/main_loop/request_metrics.rs37
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs10
-rw-r--r--crates/stdx/src/lib.rs1
-rw-r--r--crates/vfs/Cargo.toml14
-rw-r--r--crates/vfs/src/file_set.rs113
-rw-r--r--crates/vfs/src/lib.rs141
-rw-r--r--crates/vfs/src/loader.rs69
-rw-r--r--crates/vfs/src/path_interner.rs31
-rw-r--r--crates/vfs/src/vfs_path.rs49
-rw-r--r--crates/vfs/src/walkdir_loader.rs108
-rw-r--r--docs/dev/README.md40
-rw-r--r--editors/code/package.json23
-rw-r--r--editors/code/src/commands.ts14
-rw-r--r--editors/code/src/config.ts5
-rw-r--r--editors/code/src/debug.ts2
-rw-r--r--editors/code/src/main.ts17
-rw-r--r--editors/code/src/net.ts54
125 files changed, 6348 insertions, 1996 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5848e61c7..d909bc3d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,14 +2,20 @@
2# It is not intended for manual editing. 2# It is not intended for manual editing.
3[[package]] 3[[package]]
4name = "addr2line" 4name = "addr2line"
5version = "0.12.1" 5version = "0.12.2"
6source = "registry+https://github.com/rust-lang/crates.io-index" 6source = "registry+https://github.com/rust-lang/crates.io-index"
7checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" 7checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c"
8dependencies = [ 8dependencies = [
9 "gimli", 9 "gimli",
10] 10]
11 11
12[[package]] 12[[package]]
13name = "adler32"
14version = "1.1.0"
15source = "registry+https://github.com/rust-lang/crates.io-index"
16checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
17
18[[package]]
13name = "aho-corasick" 19name = "aho-corasick"
14version = "0.7.10" 20version = "0.7.10"
15source = "registry+https://github.com/rust-lang/crates.io-index" 21source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -55,22 +61,23 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
55 61
56[[package]] 62[[package]]
57name = "backtrace" 63name = "backtrace"
58version = "0.3.48" 64version = "0.3.49"
59source = "registry+https://github.com/rust-lang/crates.io-index" 65source = "registry+https://github.com/rust-lang/crates.io-index"
60checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" 66checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
61dependencies = [ 67dependencies = [
62 "addr2line", 68 "addr2line",
63 "cfg-if", 69 "cfg-if",
64 "libc", 70 "libc",
71 "miniz_oxide",
65 "object", 72 "object",
66 "rustc-demangle", 73 "rustc-demangle",
67] 74]
68 75
69[[package]] 76[[package]]
70name = "base64" 77name = "base64"
71version = "0.12.1" 78version = "0.12.2"
72source = "registry+https://github.com/rust-lang/crates.io-index" 79source = "registry+https://github.com/rust-lang/crates.io-index"
73checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" 80checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67"
74 81
75[[package]] 82[[package]]
76name = "bitflags" 83name = "bitflags"
@@ -281,9 +288,9 @@ checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f"
281 288
282[[package]] 289[[package]]
283name = "dtoa" 290name = "dtoa"
284version = "0.4.5" 291version = "0.4.6"
285source = "registry+https://github.com/rust-lang/crates.io-index" 292source = "registry+https://github.com/rust-lang/crates.io-index"
286checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" 293checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
287 294
288[[package]] 295[[package]]
289name = "either" 296name = "either"
@@ -438,9 +445,9 @@ dependencies = [
438 445
439[[package]] 446[[package]]
440name = "hermit-abi" 447name = "hermit-abi"
441version = "0.1.13" 448version = "0.1.14"
442source = "registry+https://github.com/rust-lang/crates.io-index" 449source = "registry+https://github.com/rust-lang/crates.io-index"
443checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" 450checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
444dependencies = [ 451dependencies = [
445 "libc", 452 "libc",
446] 453]
@@ -528,9 +535,9 @@ dependencies = [
528 535
529[[package]] 536[[package]]
530name = "itoa" 537name = "itoa"
531version = "0.4.5" 538version = "0.4.6"
532source = "registry+https://github.com/rust-lang/crates.io-index" 539source = "registry+https://github.com/rust-lang/crates.io-index"
533checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 540checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
534 541
535[[package]] 542[[package]]
536name = "jemalloc-ctl" 543name = "jemalloc-ctl"
@@ -633,9 +640,9 @@ dependencies = [
633 640
634[[package]] 641[[package]]
635name = "lsp-server" 642name = "lsp-server"
636version = "0.3.2" 643version = "0.3.3"
637source = "registry+https://github.com/rust-lang/crates.io-index" 644source = "registry+https://github.com/rust-lang/crates.io-index"
638checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072" 645checksum = "53b4ace8ebe5d2aff3687ce0ed507f6020d6a47a7de2b0d3d664ea237ffb0c62"
639dependencies = [ 646dependencies = [
640 "crossbeam-channel", 647 "crossbeam-channel",
641 "log", 648 "log",
@@ -695,6 +702,15 @@ dependencies = [
695] 702]
696 703
697[[package]] 704[[package]]
705name = "miniz_oxide"
706version = "0.3.7"
707source = "registry+https://github.com/rust-lang/crates.io-index"
708checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
709dependencies = [
710 "adler32",
711]
712
713[[package]]
698name = "mio" 714name = "mio"
699version = "0.6.22" 715version = "0.6.22"
700source = "registry+https://github.com/rust-lang/crates.io-index" 716source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -778,9 +794,9 @@ dependencies = [
778 794
779[[package]] 795[[package]]
780name = "object" 796name = "object"
781version = "0.19.0" 797version = "0.20.0"
782source = "registry+https://github.com/rust-lang/crates.io-index" 798source = "registry+https://github.com/rust-lang/crates.io-index"
783checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" 799checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
784 800
785[[package]] 801[[package]]
786name = "once_cell" 802name = "once_cell"
@@ -814,9 +830,9 @@ dependencies = [
814 830
815[[package]] 831[[package]]
816name = "paste" 832name = "paste"
817version = "0.1.16" 833version = "0.1.18"
818source = "registry+https://github.com/rust-lang/crates.io-index" 834source = "registry+https://github.com/rust-lang/crates.io-index"
819checksum = "d508492eeb1e5c38ee696371bf7b9fc33c83d46a7d451606b96458fbbbdc2dec" 835checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
820dependencies = [ 836dependencies = [
821 "paste-impl", 837 "paste-impl",
822 "proc-macro-hack", 838 "proc-macro-hack",
@@ -824,14 +840,11 @@ dependencies = [
824 840
825[[package]] 841[[package]]
826name = "paste-impl" 842name = "paste-impl"
827version = "0.1.16" 843version = "0.1.18"
828source = "registry+https://github.com/rust-lang/crates.io-index" 844source = "registry+https://github.com/rust-lang/crates.io-index"
829checksum = "84f328a6a63192b333fce5fbb4be79db6758a4d518dfac6d54412f1492f72d32" 845checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
830dependencies = [ 846dependencies = [
831 "proc-macro-hack", 847 "proc-macro-hack",
832 "proc-macro2",
833 "quote",
834 "syn",
835] 848]
836 849
837[[package]] 850[[package]]
@@ -856,9 +869,9 @@ dependencies = [
856 869
857[[package]] 870[[package]]
858name = "pico-args" 871name = "pico-args"
859version = "0.3.1" 872version = "0.3.2"
860source = "registry+https://github.com/rust-lang/crates.io-index" 873source = "registry+https://github.com/rust-lang/crates.io-index"
861checksum = "3ad1f1b834a05d42dae330066e9699a173b28185b3bdc3dbf14ca239585de8cc" 874checksum = "6a71836ceac43f0349e3bd964f5bb902f7b003916f32a4ad00354dafc447fa8f"
862 875
863[[package]] 876[[package]]
864name = "plain" 877name = "plain"
@@ -1062,6 +1075,7 @@ dependencies = [
1062 "ra_hir", 1075 "ra_hir",
1063 "ra_ide_db", 1076 "ra_ide_db",
1064 "ra_prof", 1077 "ra_prof",
1078 "ra_ssr",
1065 "ra_syntax", 1079 "ra_syntax",
1066 "ra_text_edit", 1080 "ra_text_edit",
1067 "rand", 1081 "rand",
@@ -1167,6 +1181,18 @@ dependencies = [
1167] 1181]
1168 1182
1169[[package]] 1183[[package]]
1184name = "ra_ssr"
1185version = "0.1.0"
1186dependencies = [
1187 "ra_db",
1188 "ra_hir",
1189 "ra_ide_db",
1190 "ra_syntax",
1191 "ra_text_edit",
1192 "rustc-hash",
1193]
1194
1195[[package]]
1170name = "ra_syntax" 1196name = "ra_syntax"
1171version = "0.1.0" 1197version = "0.1.0"
1172dependencies = [ 1198dependencies = [
@@ -1275,10 +1301,11 @@ dependencies = [
1275 1301
1276[[package]] 1302[[package]]
1277name = "rayon" 1303name = "rayon"
1278version = "1.3.0" 1304version = "1.3.1"
1279source = "registry+https://github.com/rust-lang/crates.io-index" 1305source = "registry+https://github.com/rust-lang/crates.io-index"
1280checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" 1306checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080"
1281dependencies = [ 1307dependencies = [
1308 "autocfg",
1282 "crossbeam-deque", 1309 "crossbeam-deque",
1283 "either", 1310 "either",
1284 "rayon-core", 1311 "rayon-core",
@@ -1286,9 +1313,9 @@ dependencies = [
1286 1313
1287[[package]] 1314[[package]]
1288name = "rayon-core" 1315name = "rayon-core"
1289version = "1.7.0" 1316version = "1.7.1"
1290source = "registry+https://github.com/rust-lang/crates.io-index" 1317source = "registry+https://github.com/rust-lang/crates.io-index"
1291checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" 1318checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280"
1292dependencies = [ 1319dependencies = [
1293 "crossbeam-deque", 1320 "crossbeam-deque",
1294 "crossbeam-queue", 1321 "crossbeam-queue",
@@ -1323,15 +1350,15 @@ checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
1323 1350
1324[[package]] 1351[[package]]
1325name = "relative-path" 1352name = "relative-path"
1326version = "1.0.0" 1353version = "1.2.1"
1327source = "registry+https://github.com/rust-lang/crates.io-index" 1354source = "registry+https://github.com/rust-lang/crates.io-index"
1328checksum = "bedde000f40f2921ce439ea165c9c53fd629bfa115140c72e22aceacb4a21954" 1355checksum = "c602122c47b382cd045b10866a084b184035d45d8c2609cdd3762852ddfae2a1"
1329 1356
1330[[package]] 1357[[package]]
1331name = "remove_dir_all" 1358name = "remove_dir_all"
1332version = "0.5.2" 1359version = "0.5.3"
1333source = "registry+https://github.com/rust-lang/crates.io-index" 1360source = "registry+https://github.com/rust-lang/crates.io-index"
1334checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" 1361checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
1335dependencies = [ 1362dependencies = [
1336 "winapi 0.3.8", 1363 "winapi 0.3.8",
1337] 1364]
@@ -1505,18 +1532,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1505 1532
1506[[package]] 1533[[package]]
1507name = "serde" 1534name = "serde"
1508version = "1.0.111" 1535version = "1.0.113"
1509source = "registry+https://github.com/rust-lang/crates.io-index" 1536source = "registry+https://github.com/rust-lang/crates.io-index"
1510checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" 1537checksum = "6135c78461981c79497158ef777264c51d9d0f4f3fc3a4d22b915900e42dac6a"
1511dependencies = [ 1538dependencies = [
1512 "serde_derive", 1539 "serde_derive",
1513] 1540]
1514 1541
1515[[package]] 1542[[package]]
1516name = "serde_derive" 1543name = "serde_derive"
1517version = "1.0.111" 1544version = "1.0.113"
1518source = "registry+https://github.com/rust-lang/crates.io-index" 1545source = "registry+https://github.com/rust-lang/crates.io-index"
1519checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" 1546checksum = "93c5eaa17d0954cb481cdcfffe9d84fcfa7a1a9f2349271e678677be4c26ae31"
1520dependencies = [ 1547dependencies = [
1521 "proc-macro2", 1548 "proc-macro2",
1522 "quote", 1549 "quote",
@@ -1536,9 +1563,9 @@ dependencies = [
1536 1563
1537[[package]] 1564[[package]]
1538name = "serde_repr" 1565name = "serde_repr"
1539version = "0.1.5" 1566version = "0.1.6"
1540source = "registry+https://github.com/rust-lang/crates.io-index" 1567source = "registry+https://github.com/rust-lang/crates.io-index"
1541checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" 1568checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
1542dependencies = [ 1569dependencies = [
1543 "proc-macro2", 1570 "proc-macro2",
1544 "quote", 1571 "quote",
@@ -1590,9 +1617,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1590 1617
1591[[package]] 1618[[package]]
1592name = "syn" 1619name = "syn"
1593version = "1.0.31" 1620version = "1.0.32"
1594source = "registry+https://github.com/rust-lang/crates.io-index" 1621source = "registry+https://github.com/rust-lang/crates.io-index"
1595checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" 1622checksum = "a994520748611c17d163e81b6c4a4b13d11b7f63884362ab2efac3aa9cf16d00"
1596dependencies = [ 1623dependencies = [
1597 "proc-macro2", 1624 "proc-macro2",
1598 "quote", 1625 "quote",
@@ -1688,6 +1715,12 @@ dependencies = [
1688] 1715]
1689 1716
1690[[package]] 1717[[package]]
1718name = "tinyvec"
1719version = "0.3.3"
1720source = "registry+https://github.com/rust-lang/crates.io-index"
1721checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
1722
1723[[package]]
1691name = "unicode-bidi" 1724name = "unicode-bidi"
1692version = "0.3.4" 1725version = "0.3.4"
1693source = "registry+https://github.com/rust-lang/crates.io-index" 1726source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1698,11 +1731,11 @@ dependencies = [
1698 1731
1699[[package]] 1732[[package]]
1700name = "unicode-normalization" 1733name = "unicode-normalization"
1701version = "0.1.12" 1734version = "0.1.13"
1702source = "registry+https://github.com/rust-lang/crates.io-index" 1735source = "registry+https://github.com/rust-lang/crates.io-index"
1703checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" 1736checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
1704dependencies = [ 1737dependencies = [
1705 "smallvec", 1738 "tinyvec",
1706] 1739]
1707 1740
1708[[package]] 1741[[package]]
@@ -1730,6 +1763,18 @@ dependencies = [
1730] 1763]
1731 1764
1732[[package]] 1765[[package]]
1766name = "vfs"
1767version = "0.1.0"
1768dependencies = [
1769 "crossbeam-channel",
1770 "globset",
1771 "jod-thread",
1772 "paths",
1773 "rustc-hash",
1774 "walkdir",
1775]
1776
1777[[package]]
1733name = "walkdir" 1778name = "walkdir"
1734version = "2.3.1" 1779version = "2.3.1"
1735source = "registry+https://github.com/rust-lang/crates.io-index" 1780source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index c7ce0c42f..190c50913 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -2,7 +2,7 @@
2//! relative paths. 2//! relative paths.
3use std::{ 3use std::{
4 convert::{TryFrom, TryInto}, 4 convert::{TryFrom, TryInto},
5 ops, 5 io, ops,
6 path::{Component, Path, PathBuf}, 6 path::{Component, Path, PathBuf},
7}; 7};
8 8
@@ -46,6 +46,9 @@ impl TryFrom<&str> for AbsPathBuf {
46} 46}
47 47
48impl AbsPathBuf { 48impl AbsPathBuf {
49 pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
50 path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
51 }
49 pub fn as_path(&self) -> &AbsPath { 52 pub fn as_path(&self) -> &AbsPath {
50 AbsPath::new_unchecked(self.0.as_path()) 53 AbsPath::new_unchecked(self.0.as_path())
51 } 54 }
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index edd8255f4..ee614de72 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -252,7 +252,7 @@ impl AssistBuilder {
252 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) { 252 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) {
253 let node = rewriter.rewrite_root().unwrap(); 253 let node = rewriter.rewrite_root().unwrap();
254 let new = rewriter.rewrite(&node); 254 let new = rewriter.rewrite(&node);
255 algo::diff(&node, &new).into_text_edit(&mut self.edit) 255 algo::diff(&node, &new).into_text_edit(&mut self.edit);
256 } 256 }
257 257
258 // FIXME: kill this API 258 // FIXME: kill this API
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
index 0197a8cf0..b4784c333 100644
--- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -1,7 +1,10 @@
1use hir; 1use hir;
2use ra_syntax::{ast, AstNode, SmolStr, TextRange}; 2use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode};
3 3
4use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists}; 4use crate::{
5 utils::{find_insert_use_container, insert_use_statement},
6 AssistContext, AssistId, Assists,
7};
5 8
6// Assist: replace_qualified_name_with_use 9// Assist: replace_qualified_name_with_use
7// 10//
@@ -39,16 +42,18 @@ pub(crate) fn replace_qualified_name_with_use(
39 target, 42 target,
40 |builder| { 43 |builder| {
41 let path_to_import = hir_path.mod_path().clone(); 44 let path_to_import = hir_path.mod_path().clone();
45 let container = match find_insert_use_container(path.syntax(), ctx) {
46 Some(c) => c,
47 None => return,
48 };
42 insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder()); 49 insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder());
43 50
44 if let Some(last) = path.segment() { 51 // Now that we've brought the name into scope, re-qualify all paths that could be
45 // Here we are assuming the assist will provide a correct use statement 52 // affected (that is, all paths inside the node we added the `use` to).
46 // so we can delete the path qualifier 53 let mut rewriter = SyntaxRewriter::default();
47 builder.delete(TextRange::new( 54 let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone());
48 path.syntax().text_range().start(), 55 shorten_paths(&mut rewriter, syntax, path);
49 last.syntax().text_range().start(), 56 builder.rewrite(rewriter);
50 ));
51 }
52 }, 57 },
53 ) 58 )
54} 59}
@@ -73,6 +78,69 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
73 Some(ps) 78 Some(ps)
74} 79}
75 80
81/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
82fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: ast::Path) {
83 for child in node.children() {
84 match_ast! {
85 match child {
86 // Don't modify `use` items, as this can break the `use` item when injecting a new
87 // import into the use tree.
88 ast::UseItem(_it) => continue,
89 // Don't descend into submodules, they don't have the same `use` items in scope.
90 ast::Module(_it) => continue,
91
92 ast::Path(p) => {
93 match maybe_replace_path(rewriter, p.clone(), path.clone()) {
94 Some(()) => {},
95 None => shorten_paths(rewriter, p.syntax().clone(), path.clone()),
96 }
97 },
98 _ => shorten_paths(rewriter, child, path.clone()),
99 }
100 }
101 }
102}
103
104fn maybe_replace_path(
105 rewriter: &mut SyntaxRewriter<'static>,
106 path: ast::Path,
107 target: ast::Path,
108) -> Option<()> {
109 if !path_eq(path.clone(), target.clone()) {
110 return None;
111 }
112
113 // Shorten `path`, leaving only its last segment.
114 if let Some(parent) = path.qualifier() {
115 rewriter.delete(parent.syntax());
116 }
117 if let Some(double_colon) = path.coloncolon_token() {
118 rewriter.delete(&double_colon);
119 }
120
121 Some(())
122}
123
124fn path_eq(lhs: ast::Path, rhs: ast::Path) -> bool {
125 let mut lhs_curr = lhs;
126 let mut rhs_curr = rhs;
127 loop {
128 match (lhs_curr.segment(), rhs_curr.segment()) {
129 (Some(lhs), Some(rhs)) if lhs.syntax().text() == rhs.syntax().text() => (),
130 _ => return false,
131 }
132
133 match (lhs_curr.qualifier(), rhs_curr.qualifier()) {
134 (Some(lhs), Some(rhs)) => {
135 lhs_curr = lhs;
136 rhs_curr = rhs;
137 }
138 (None, None) => return true,
139 _ => return false,
140 }
141 }
142}
143
76#[cfg(test)] 144#[cfg(test)]
77mod tests { 145mod tests {
78 use crate::tests::{check_assist, check_assist_not_applicable}; 146 use crate::tests::{check_assist, check_assist_not_applicable};
@@ -83,10 +151,10 @@ mod tests {
83 fn test_replace_add_use_no_anchor() { 151 fn test_replace_add_use_no_anchor() {
84 check_assist( 152 check_assist(
85 replace_qualified_name_with_use, 153 replace_qualified_name_with_use,
86 " 154 r"
87std::fmt::Debug<|> 155std::fmt::Debug<|>
88 ", 156 ",
89 " 157 r"
90use std::fmt::Debug; 158use std::fmt::Debug;
91 159
92Debug 160Debug
@@ -97,13 +165,13 @@ Debug
97 fn test_replace_add_use_no_anchor_with_item_below() { 165 fn test_replace_add_use_no_anchor_with_item_below() {
98 check_assist( 166 check_assist(
99 replace_qualified_name_with_use, 167 replace_qualified_name_with_use,
100 " 168 r"
101std::fmt::Debug<|> 169std::fmt::Debug<|>
102 170
103fn main() { 171fn main() {
104} 172}
105 ", 173 ",
106 " 174 r"
107use std::fmt::Debug; 175use std::fmt::Debug;
108 176
109Debug 177Debug
@@ -118,13 +186,13 @@ fn main() {
118 fn test_replace_add_use_no_anchor_with_item_above() { 186 fn test_replace_add_use_no_anchor_with_item_above() {
119 check_assist( 187 check_assist(
120 replace_qualified_name_with_use, 188 replace_qualified_name_with_use,
121 " 189 r"
122fn main() { 190fn main() {
123} 191}
124 192
125std::fmt::Debug<|> 193std::fmt::Debug<|>
126 ", 194 ",
127 " 195 r"
128use std::fmt::Debug; 196use std::fmt::Debug;
129 197
130fn main() { 198fn main() {
@@ -139,10 +207,10 @@ Debug
139 fn test_replace_add_use_no_anchor_2seg() { 207 fn test_replace_add_use_no_anchor_2seg() {
140 check_assist( 208 check_assist(
141 replace_qualified_name_with_use, 209 replace_qualified_name_with_use,
142 " 210 r"
143std::fmt<|>::Debug 211std::fmt<|>::Debug
144 ", 212 ",
145 " 213 r"
146use std::fmt; 214use std::fmt;
147 215
148fmt::Debug 216fmt::Debug
@@ -154,13 +222,13 @@ fmt::Debug
154 fn test_replace_add_use() { 222 fn test_replace_add_use() {
155 check_assist( 223 check_assist(
156 replace_qualified_name_with_use, 224 replace_qualified_name_with_use,
157 " 225 r"
158use stdx; 226use stdx;
159 227
160impl std::fmt::Debug<|> for Foo { 228impl std::fmt::Debug<|> for Foo {
161} 229}
162 ", 230 ",
163 " 231 r"
164use stdx; 232use stdx;
165use std::fmt::Debug; 233use std::fmt::Debug;
166 234
@@ -174,11 +242,11 @@ impl Debug for Foo {
174 fn test_replace_file_use_other_anchor() { 242 fn test_replace_file_use_other_anchor() {
175 check_assist( 243 check_assist(
176 replace_qualified_name_with_use, 244 replace_qualified_name_with_use,
177 " 245 r"
178impl std::fmt::Debug<|> for Foo { 246impl std::fmt::Debug<|> for Foo {
179} 247}
180 ", 248 ",
181 " 249 r"
182use std::fmt::Debug; 250use std::fmt::Debug;
183 251
184impl Debug for Foo { 252impl Debug for Foo {
@@ -191,11 +259,11 @@ impl Debug for Foo {
191 fn test_replace_add_use_other_anchor_indent() { 259 fn test_replace_add_use_other_anchor_indent() {
192 check_assist( 260 check_assist(
193 replace_qualified_name_with_use, 261 replace_qualified_name_with_use,
194 " 262 r"
195 impl std::fmt::Debug<|> for Foo { 263 impl std::fmt::Debug<|> for Foo {
196 } 264 }
197 ", 265 ",
198 " 266 r"
199 use std::fmt::Debug; 267 use std::fmt::Debug;
200 268
201 impl Debug for Foo { 269 impl Debug for Foo {
@@ -208,13 +276,13 @@ impl Debug for Foo {
208 fn test_replace_split_different() { 276 fn test_replace_split_different() {
209 check_assist( 277 check_assist(
210 replace_qualified_name_with_use, 278 replace_qualified_name_with_use,
211 " 279 r"
212use std::fmt; 280use std::fmt;
213 281
214impl std::io<|> for Foo { 282impl std::io<|> for Foo {
215} 283}
216 ", 284 ",
217 " 285 r"
218use std::{io, fmt}; 286use std::{io, fmt};
219 287
220impl io for Foo { 288impl io for Foo {
@@ -227,13 +295,13 @@ impl io for Foo {
227 fn test_replace_split_self_for_use() { 295 fn test_replace_split_self_for_use() {
228 check_assist( 296 check_assist(
229 replace_qualified_name_with_use, 297 replace_qualified_name_with_use,
230 " 298 r"
231use std::fmt; 299use std::fmt;
232 300
233impl std::fmt::Debug<|> for Foo { 301impl std::fmt::Debug<|> for Foo {
234} 302}
235 ", 303 ",
236 " 304 r"
237use std::fmt::{self, Debug, }; 305use std::fmt::{self, Debug, };
238 306
239impl Debug for Foo { 307impl Debug for Foo {
@@ -246,13 +314,13 @@ impl Debug for Foo {
246 fn test_replace_split_self_for_target() { 314 fn test_replace_split_self_for_target() {
247 check_assist( 315 check_assist(
248 replace_qualified_name_with_use, 316 replace_qualified_name_with_use,
249 " 317 r"
250use std::fmt::Debug; 318use std::fmt::Debug;
251 319
252impl std::fmt<|> for Foo { 320impl std::fmt<|> for Foo {
253} 321}
254 ", 322 ",
255 " 323 r"
256use std::fmt::{self, Debug}; 324use std::fmt::{self, Debug};
257 325
258impl fmt for Foo { 326impl fmt for Foo {
@@ -265,13 +333,13 @@ impl fmt for Foo {
265 fn test_replace_add_to_nested_self_nested() { 333 fn test_replace_add_to_nested_self_nested() {
266 check_assist( 334 check_assist(
267 replace_qualified_name_with_use, 335 replace_qualified_name_with_use,
268 " 336 r"
269use std::fmt::{Debug, nested::{Display}}; 337use std::fmt::{Debug, nested::{Display}};
270 338
271impl std::fmt::nested<|> for Foo { 339impl std::fmt::nested<|> for Foo {
272} 340}
273", 341",
274 " 342 r"
275use std::fmt::{Debug, nested::{Display, self}}; 343use std::fmt::{Debug, nested::{Display, self}};
276 344
277impl nested for Foo { 345impl nested for Foo {
@@ -284,13 +352,13 @@ impl nested for Foo {
284 fn test_replace_add_to_nested_self_already_included() { 352 fn test_replace_add_to_nested_self_already_included() {
285 check_assist( 353 check_assist(
286 replace_qualified_name_with_use, 354 replace_qualified_name_with_use,
287 " 355 r"
288use std::fmt::{Debug, nested::{self, Display}}; 356use std::fmt::{Debug, nested::{self, Display}};
289 357
290impl std::fmt::nested<|> for Foo { 358impl std::fmt::nested<|> for Foo {
291} 359}
292", 360",
293 " 361 r"
294use std::fmt::{Debug, nested::{self, Display}}; 362use std::fmt::{Debug, nested::{self, Display}};
295 363
296impl nested for Foo { 364impl nested for Foo {
@@ -303,13 +371,13 @@ impl nested for Foo {
303 fn test_replace_add_to_nested_nested() { 371 fn test_replace_add_to_nested_nested() {
304 check_assist( 372 check_assist(
305 replace_qualified_name_with_use, 373 replace_qualified_name_with_use,
306 " 374 r"
307use std::fmt::{Debug, nested::{Display}}; 375use std::fmt::{Debug, nested::{Display}};
308 376
309impl std::fmt::nested::Debug<|> for Foo { 377impl std::fmt::nested::Debug<|> for Foo {
310} 378}
311", 379",
312 " 380 r"
313use std::fmt::{Debug, nested::{Display, Debug}}; 381use std::fmt::{Debug, nested::{Display, Debug}};
314 382
315impl Debug for Foo { 383impl Debug for Foo {
@@ -322,13 +390,13 @@ impl Debug for Foo {
322 fn test_replace_split_common_target_longer() { 390 fn test_replace_split_common_target_longer() {
323 check_assist( 391 check_assist(
324 replace_qualified_name_with_use, 392 replace_qualified_name_with_use,
325 " 393 r"
326use std::fmt::Debug; 394use std::fmt::Debug;
327 395
328impl std::fmt::nested::Display<|> for Foo { 396impl std::fmt::nested::Display<|> for Foo {
329} 397}
330", 398",
331 " 399 r"
332use std::fmt::{nested::Display, Debug}; 400use std::fmt::{nested::Display, Debug};
333 401
334impl Display for Foo { 402impl Display for Foo {
@@ -341,13 +409,13 @@ impl Display for Foo {
341 fn test_replace_split_common_use_longer() { 409 fn test_replace_split_common_use_longer() {
342 check_assist( 410 check_assist(
343 replace_qualified_name_with_use, 411 replace_qualified_name_with_use,
344 " 412 r"
345use std::fmt::nested::Debug; 413use std::fmt::nested::Debug;
346 414
347impl std::fmt::Display<|> for Foo { 415impl std::fmt::Display<|> for Foo {
348} 416}
349", 417",
350 " 418 r"
351use std::fmt::{Display, nested::Debug}; 419use std::fmt::{Display, nested::Debug};
352 420
353impl Display for Foo { 421impl Display for Foo {
@@ -360,7 +428,7 @@ impl Display for Foo {
360 fn test_replace_use_nested_import() { 428 fn test_replace_use_nested_import() {
361 check_assist( 429 check_assist(
362 replace_qualified_name_with_use, 430 replace_qualified_name_with_use,
363 " 431 r"
364use crate::{ 432use crate::{
365 ty::{Substs, Ty}, 433 ty::{Substs, Ty},
366 AssocItem, 434 AssocItem,
@@ -368,7 +436,7 @@ use crate::{
368 436
369fn foo() { crate::ty::lower<|>::trait_env() } 437fn foo() { crate::ty::lower<|>::trait_env() }
370", 438",
371 " 439 r"
372use crate::{ 440use crate::{
373 ty::{Substs, Ty, lower}, 441 ty::{Substs, Ty, lower},
374 AssocItem, 442 AssocItem,
@@ -383,13 +451,13 @@ fn foo() { lower::trait_env() }
383 fn test_replace_alias() { 451 fn test_replace_alias() {
384 check_assist( 452 check_assist(
385 replace_qualified_name_with_use, 453 replace_qualified_name_with_use,
386 " 454 r"
387use std::fmt as foo; 455use std::fmt as foo;
388 456
389impl foo::Debug<|> for Foo { 457impl foo::Debug<|> for Foo {
390} 458}
391", 459",
392 " 460 r"
393use std::fmt as foo; 461use std::fmt as foo;
394 462
395impl Debug for Foo { 463impl Debug for Foo {
@@ -402,7 +470,7 @@ impl Debug for Foo {
402 fn test_replace_not_applicable_one_segment() { 470 fn test_replace_not_applicable_one_segment() {
403 check_assist_not_applicable( 471 check_assist_not_applicable(
404 replace_qualified_name_with_use, 472 replace_qualified_name_with_use,
405 " 473 r"
406impl foo<|> for Foo { 474impl foo<|> for Foo {
407} 475}
408", 476",
@@ -413,7 +481,7 @@ impl foo<|> for Foo {
413 fn test_replace_not_applicable_in_use() { 481 fn test_replace_not_applicable_in_use() {
414 check_assist_not_applicable( 482 check_assist_not_applicable(
415 replace_qualified_name_with_use, 483 replace_qualified_name_with_use,
416 " 484 r"
417use std::fmt<|>; 485use std::fmt<|>;
418", 486",
419 ); 487 );
@@ -423,14 +491,14 @@ use std::fmt<|>;
423 fn test_replace_add_use_no_anchor_in_mod_mod() { 491 fn test_replace_add_use_no_anchor_in_mod_mod() {
424 check_assist( 492 check_assist(
425 replace_qualified_name_with_use, 493 replace_qualified_name_with_use,
426 " 494 r"
427mod foo { 495mod foo {
428 mod bar { 496 mod bar {
429 std::fmt::Debug<|> 497 std::fmt::Debug<|>
430 } 498 }
431} 499}
432 ", 500 ",
433 " 501 r"
434mod foo { 502mod foo {
435 mod bar { 503 mod bar {
436 use std::fmt::Debug; 504 use std::fmt::Debug;
@@ -446,14 +514,14 @@ mod foo {
446 fn inserts_imports_after_inner_attributes() { 514 fn inserts_imports_after_inner_attributes() {
447 check_assist( 515 check_assist(
448 replace_qualified_name_with_use, 516 replace_qualified_name_with_use,
449 " 517 r"
450#![allow(dead_code)] 518#![allow(dead_code)]
451 519
452fn main() { 520fn main() {
453 std::fmt::Debug<|> 521 std::fmt::Debug<|>
454} 522}
455 ", 523 ",
456 " 524 r"
457#![allow(dead_code)] 525#![allow(dead_code)]
458use std::fmt::Debug; 526use std::fmt::Debug;
459 527
@@ -463,4 +531,116 @@ fn main() {
463 ", 531 ",
464 ); 532 );
465 } 533 }
534
535 #[test]
536 fn replaces_all_affected_paths() {
537 check_assist(
538 replace_qualified_name_with_use,
539 r"
540fn main() {
541 std::fmt::Debug<|>;
542 let x: std::fmt::Debug = std::fmt::Debug;
543}
544 ",
545 r"
546use std::fmt::Debug;
547
548fn main() {
549 Debug;
550 let x: Debug = Debug;
551}
552 ",
553 );
554 }
555
556 #[test]
557 fn replaces_all_affected_paths_mod() {
558 check_assist(
559 replace_qualified_name_with_use,
560 r"
561mod m {
562 fn f() {
563 std::fmt::Debug<|>;
564 let x: std::fmt::Debug = std::fmt::Debug;
565 }
566 fn g() {
567 std::fmt::Debug;
568 }
569}
570
571fn f() {
572 std::fmt::Debug;
573}
574 ",
575 r"
576mod m {
577 use std::fmt::Debug;
578
579 fn f() {
580 Debug;
581 let x: Debug = Debug;
582 }
583 fn g() {
584 Debug;
585 }
586}
587
588fn f() {
589 std::fmt::Debug;
590}
591 ",
592 );
593 }
594
595 #[test]
596 fn does_not_replace_in_submodules() {
597 check_assist(
598 replace_qualified_name_with_use,
599 r"
600fn main() {
601 std::fmt::Debug<|>;
602}
603
604mod sub {
605 fn f() {
606 std::fmt::Debug;
607 }
608}
609 ",
610 r"
611use std::fmt::Debug;
612
613fn main() {
614 Debug;
615}
616
617mod sub {
618 fn f() {
619 std::fmt::Debug;
620 }
621}
622 ",
623 );
624 }
625
626 #[test]
627 fn does_not_replace_in_use() {
628 check_assist(
629 replace_qualified_name_with_use,
630 r"
631use std::fmt::Display;
632
633fn main() {
634 std::fmt<|>;
635}
636 ",
637 r"
638use std::fmt::{self, Display};
639
640fn main() {
641 fmt;
642}
643 ",
644 );
645 }
466} 646}
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 0038a9764..c1ff0de7b 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -13,7 +13,7 @@ use rustc_hash::FxHashSet;
13 13
14use crate::assist_config::SnippetCap; 14use crate::assist_config::SnippetCap;
15 15
16pub(crate) use insert_use::insert_use_statement; 16pub(crate) use insert_use::{find_insert_use_container, insert_use_statement};
17 17
18#[derive(Clone, Copy, Debug)] 18#[derive(Clone, Copy, Debug)]
19pub(crate) enum Cursor<'a> { 19pub(crate) enum Cursor<'a> {
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs
index 0ee43482f..8c4f33e59 100644
--- a/crates/ra_assists/src/utils/insert_use.rs
+++ b/crates/ra_assists/src/utils/insert_use.rs
@@ -12,6 +12,20 @@ use ra_syntax::{
12use ra_text_edit::TextEditBuilder; 12use ra_text_edit::TextEditBuilder;
13 13
14use crate::assist_context::AssistContext; 14use crate::assist_context::AssistContext;
15use either::Either;
16
17/// Determines the containing syntax node in which to insert a `use` statement affecting `position`.
18pub(crate) fn find_insert_use_container(
19 position: &SyntaxNode,
20 ctx: &AssistContext,
21) -> Option<Either<ast::ItemList, ast::SourceFile>> {
22 ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| {
23 if let Some(module) = ast::Module::cast(n.clone()) {
24 return module.item_list().map(|it| Either::Left(it));
25 }
26 Some(Either::Right(ast::SourceFile::cast(n)?))
27 })
28}
15 29
16/// Creates and inserts a use statement for the given path to import. 30/// Creates and inserts a use statement for the given path to import.
17/// The use statement is inserted in the scope most appropriate to the 31/// The use statement is inserted in the scope most appropriate to the
@@ -24,15 +38,11 @@ pub(crate) fn insert_use_statement(
24 builder: &mut TextEditBuilder, 38 builder: &mut TextEditBuilder,
25) { 39) {
26 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); 40 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>();
27 let container = ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| { 41 let container = find_insert_use_container(position, ctx);
28 if let Some(module) = ast::Module::cast(n.clone()) {
29 return module.item_list().map(|it| it.syntax().clone());
30 }
31 ast::SourceFile::cast(n).map(|it| it.syntax().clone())
32 });
33 42
34 if let Some(container) = container { 43 if let Some(container) = container {
35 let action = best_action_for_target(container, position.clone(), &target); 44 let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone());
45 let action = best_action_for_target(syntax, position.clone(), &target);
36 make_assist(&action, &target, builder); 46 make_assist(&action, &target, builder);
37 } 47 }
38} 48}
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index bf26048f2..e6af99035 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -254,12 +254,12 @@ impl CrateGraph {
254 return false; 254 return false;
255 } 255 }
256 256
257 if target == from {
258 return true;
259 }
260
257 for dep in &self[from].dependencies { 261 for dep in &self[from].dependencies {
258 let crate_id = dep.crate_id; 262 let crate_id = dep.crate_id;
259 if crate_id == target {
260 return true;
261 }
262
263 if self.dfs_find(target, crate_id, visited) { 263 if self.dfs_find(target, crate_id, visited) {
264 return true; 264 return true;
265 } 265 }
@@ -369,7 +369,7 @@ mod tests {
369 use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; 369 use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
370 370
371 #[test] 371 #[test]
372 fn it_should_panic_because_of_cycle_dependencies() { 372 fn detect_cyclic_dependency_indirect() {
373 let mut graph = CrateGraph::default(); 373 let mut graph = CrateGraph::default();
374 let crate1 = graph.add_crate_root( 374 let crate1 = graph.add_crate_root(
375 FileId(1u32), 375 FileId(1u32),
@@ -404,6 +404,31 @@ mod tests {
404 } 404 }
405 405
406 #[test] 406 #[test]
407 fn detect_cyclic_dependency_direct() {
408 let mut graph = CrateGraph::default();
409 let crate1 = graph.add_crate_root(
410 FileId(1u32),
411 Edition2018,
412 None,
413 CfgOptions::default(),
414 Env::default(),
415 Default::default(),
416 Default::default(),
417 );
418 let crate2 = graph.add_crate_root(
419 FileId(2u32),
420 Edition2018,
421 None,
422 CfgOptions::default(),
423 Env::default(),
424 Default::default(),
425 Default::default(),
426 );
427 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
428 assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err());
429 }
430
431 #[test]
407 fn it_works() { 432 fn it_works() {
408 let mut graph = CrateGraph::default(); 433 let mut graph = CrateGraph::default();
409 let crate1 = graph.add_crate_root( 434 let crate1 = graph.add_crate_root(
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1a9f6cc76..ffd5278ec 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -26,8 +26,8 @@ use hir_ty::{
26 autoderef, 26 autoderef,
27 display::{HirDisplayError, HirFormatter}, 27 display::{HirDisplayError, HirFormatter},
28 expr::ExprValidator, 28 expr::ExprValidator,
29 method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, 29 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
30 TyDefId, TypeCtor, 30 TraitEnvironment, Ty, TyDefId, TypeCtor,
31}; 31};
32use ra_db::{CrateId, CrateName, Edition, FileId}; 32use ra_db::{CrateId, CrateName, Edition, FileId};
33use ra_prof::profile; 33use ra_prof::profile;
@@ -186,6 +186,22 @@ impl ModuleDef {
186 186
187 module.visibility_of(db, self) 187 module.visibility_of(db, self)
188 } 188 }
189
190 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
191 match self {
192 ModuleDef::Adt(it) => Some(it.name(db)),
193 ModuleDef::Trait(it) => Some(it.name(db)),
194 ModuleDef::Function(it) => Some(it.name(db)),
195 ModuleDef::EnumVariant(it) => Some(it.name(db)),
196 ModuleDef::TypeAlias(it) => Some(it.name(db)),
197
198 ModuleDef::Module(it) => it.name(db),
199 ModuleDef::Const(it) => it.name(db),
200 ModuleDef::Static(it) => it.name(db),
201
202 ModuleDef::BuiltinType(it) => Some(it.as_name()),
203 }
204 }
189} 205}
190 206
191pub use hir_def::{ 207pub use hir_def::{
@@ -1359,6 +1375,27 @@ impl Type {
1359 Some(adt.into()) 1375 Some(adt.into())
1360 } 1376 }
1361 1377
1378 pub fn as_dyn_trait(&self) -> Option<Trait> {
1379 self.ty.value.dyn_trait().map(Into::into)
1380 }
1381
1382 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
1383 self.ty.value.impl_trait_bounds(db).map(|it| {
1384 it.into_iter()
1385 .filter_map(|pred| match pred {
1386 hir_ty::GenericPredicate::Implemented(trait_ref) => {
1387 Some(Trait::from(trait_ref.trait_))
1388 }
1389 _ => None,
1390 })
1391 .collect()
1392 })
1393 }
1394
1395 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
1396 self.ty.value.associated_type_parent_trait(db).map(Into::into)
1397 }
1398
1362 // FIXME: provide required accessors such that it becomes implementable from outside. 1399 // FIXME: provide required accessors such that it becomes implementable from outside.
1363 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { 1400 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
1364 match (&self.ty.value, &other.ty.value) { 1401 match (&self.ty.value, &other.ty.value) {
@@ -1380,6 +1417,80 @@ impl Type {
1380 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, 1417 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1381 } 1418 }
1382 } 1419 }
1420
1421 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
1422 // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
1423 // We need a different order here.
1424
1425 fn walk_substs(
1426 db: &dyn HirDatabase,
1427 type_: &Type,
1428 substs: &Substs,
1429 cb: &mut impl FnMut(Type),
1430 ) {
1431 for ty in substs.iter() {
1432 walk_type(db, &type_.derived(ty.clone()), cb);
1433 }
1434 }
1435
1436 fn walk_bounds(
1437 db: &dyn HirDatabase,
1438 type_: &Type,
1439 bounds: &[GenericPredicate],
1440 cb: &mut impl FnMut(Type),
1441 ) {
1442 for pred in bounds {
1443 match pred {
1444 GenericPredicate::Implemented(trait_ref) => {
1445 cb(type_.clone());
1446 walk_substs(db, type_, &trait_ref.substs, cb);
1447 }
1448 _ => (),
1449 }
1450 }
1451 }
1452
1453 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1454 let ty = type_.ty.value.strip_references();
1455 match ty {
1456 Ty::Apply(ApplicationTy { ctor, parameters }) => {
1457 match ctor {
1458 TypeCtor::Adt(_) => {
1459 cb(type_.derived(ty.clone()));
1460 }
1461 TypeCtor::AssociatedType(_) => {
1462 if let Some(_) = ty.associated_type_parent_trait(db) {
1463 cb(type_.derived(ty.clone()));
1464 }
1465 }
1466 _ => (),
1467 }
1468
1469 // adt params, tuples, etc...
1470 walk_substs(db, type_, parameters, cb);
1471 }
1472 Ty::Opaque(opaque_ty) => {
1473 if let Some(bounds) = ty.impl_trait_bounds(db) {
1474 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1475 }
1476
1477 walk_substs(db, type_, &opaque_ty.parameters, cb);
1478 }
1479 Ty::Placeholder(_) => {
1480 if let Some(bounds) = ty.impl_trait_bounds(db) {
1481 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1482 }
1483 }
1484 Ty::Dyn(bounds) => {
1485 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1486 }
1487
1488 _ => (),
1489 }
1490 }
1491
1492 walk_type(db, self, &mut cb);
1493 }
1383} 1494}
1384 1495
1385impl HirDisplay for Type { 1496impl HirDisplay for Type {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index b6b665de1..b25dac28e 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -16,7 +16,7 @@ pub use hir_expand::db::{
16pub use hir_ty::db::{ 16pub use hir_ty::db::{
17 AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, 17 AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
18 GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, 18 GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
19 HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, 19 HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery,
20 ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, 20 ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery,
21 InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, 21 InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
22 TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, 22 TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index a232a5856..6a49c424a 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -6,9 +6,9 @@ use std::{cell::RefCell, fmt, iter::successors};
6 6
7use hir_def::{ 7use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId, VariantId,
10}; 10};
11use hir_expand::{hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
@@ -104,6 +104,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
104 tree 104 tree
105 } 105 }
106 106
107 pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST {
108 let file_id = d.source().file_id;
109 let root = self.db.parse_or_expand(file_id).unwrap();
110 self.cache(root, file_id);
111 d.ast(self.db)
112 }
113
107 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { 114 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
108 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); 115 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);
109 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); 116 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
@@ -247,6 +254,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
247 self.analyze(path.syntax()).resolve_path(self.db, path) 254 self.analyze(path.syntax()).resolve_path(self.db, path)
248 } 255 }
249 256
257 pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
258 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
259 }
260
250 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { 261 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
251 let src = self.find_file(path.syntax().clone()); 262 let src = self.find_file(path.syntax().clone());
252 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) 263 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 7c6bbea13..757d1e397 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -313,6 +313,16 @@ impl SourceAnalyzer {
313 })?; 313 })?;
314 Some(macro_call_id.as_file()) 314 Some(macro_call_id.as_file())
315 } 315 }
316
317 pub(crate) fn resolve_variant(
318 &self,
319 db: &dyn HirDatabase,
320 record_lit: ast::RecordLit,
321 ) -> Option<VariantId> {
322 let infer = self.infer.as_ref()?;
323 let expr_id = self.expr_id(db, &record_lit.into())?;
324 infer.variant_resolution_for_expr(expr_id)
325 }
316} 326}
317 327
318fn scope_for( 328fn scope_for(
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index e48ff38f9..661f00407 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -87,15 +87,13 @@ impl ExprScopes {
87 } 87 }
88 88
89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
90 match &body[pat] { 90 let pattern = &body[pat];
91 Pat::Bind { name, .. } => { 91 if let Pat::Bind { name, .. } = pattern {
92 // bind can have a sub pattern, but it's actually not allowed 92 let entry = ScopeEntry { name: name.clone(), pat };
93 // to bind to things in there 93 self.scopes[scope].entries.push(entry);
94 let entry = ScopeEntry { name: name.clone(), pat };
95 self.scopes[scope].entries.push(entry)
96 }
97 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)),
98 } 94 }
95
96 pattern.walk_child_pats(|pat| self.add_bindings(body, scope, pat));
99 } 97 }
100 98
101 fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { 99 fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) {
@@ -190,8 +188,8 @@ mod tests {
190 } 188 }
191 } 189 }
192 190
193 fn do_check(code: &str, expected: &[&str]) { 191 fn do_check(ra_fixture: &str, expected: &[&str]) {
194 let (off, code) = extract_offset(code); 192 let (off, code) = extract_offset(ra_fixture);
195 let code = { 193 let code = {
196 let mut buf = String::new(); 194 let mut buf = String::new();
197 let off: usize = off.into(); 195 let off: usize = off.into();
@@ -300,6 +298,22 @@ mod tests {
300 ); 298 );
301 } 299 }
302 300
301 #[test]
302 fn test_bindings_after_at() {
303 do_check(
304 r"
305 fn foo() {
306 match Some(()) {
307 opt @ Some(unit) => {
308 <|>
309 }
310 _ => {}
311 }
312 }",
313 &["opt", "unit"],
314 );
315 }
316
303 fn do_check_local_name(code: &str, expected_offset: u32) { 317 fn do_check_local_name(code: &str, expected_offset: u32) {
304 let (off, code) = extract_offset(code); 318 let (off, code) = extract_offset(code);
305 319
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 510c5e064..30db48f86 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -3,7 +3,6 @@
3use std::any::Any; 3use std::any::Any;
4 4
5use hir_expand::diagnostics::Diagnostic; 5use hir_expand::diagnostics::Diagnostic;
6use ra_db::RelativePathBuf;
7use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
8 7
9use hir_expand::{HirFileId, InFile}; 8use hir_expand::{HirFileId, InFile};
@@ -12,7 +11,7 @@ use hir_expand::{HirFileId, InFile};
12pub struct UnresolvedModule { 11pub struct UnresolvedModule {
13 pub file: HirFileId, 12 pub file: HirFileId,
14 pub decl: AstPtr<ast::Module>, 13 pub decl: AstPtr<ast::Module>,
15 pub candidate: RelativePathBuf, 14 pub candidate: String,
16} 15}
17 16
18impl Diagnostic for UnresolvedModule { 17impl Diagnostic for UnresolvedModule {
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index edc59e5a8..af2a717c9 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -159,7 +159,7 @@ pub struct TypeAliasId(salsa::InternId);
159type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>; 159type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>;
160impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); 160impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
161 161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
163pub struct ImplId(salsa::InternId); 163pub struct ImplId(salsa::InternId);
164type ImplLoc = ItemLoc<ast::ImplDef>; 164type ImplLoc = ItemLoc<ast::ImplDef>;
165impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); 165impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index f279c2ad4..b8560fdc9 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -119,13 +119,6 @@ impl Default for ModuleOrigin {
119} 119}
120 120
121impl ModuleOrigin { 121impl ModuleOrigin {
122 pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self {
123 match file {
124 None => ModuleOrigin::Inline { definition: declaration },
125 Some(definition) => ModuleOrigin::File { declaration, definition },
126 }
127 }
128
129 fn declaration(&self) -> Option<AstId<ast::Module>> { 122 fn declaration(&self) -> Option<AstId<ast::Module>> {
130 match self { 123 match self {
131 ModuleOrigin::File { declaration: module, .. } 124 ModuleOrigin::File { declaration: module, .. }
@@ -296,7 +289,6 @@ pub enum ModuleSource {
296 289
297mod diagnostics { 290mod diagnostics {
298 use hir_expand::diagnostics::DiagnosticSink; 291 use hir_expand::diagnostics::DiagnosticSink;
299 use ra_db::RelativePathBuf;
300 use ra_syntax::{ast, AstPtr}; 292 use ra_syntax::{ast, AstPtr};
301 293
302 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId}; 294 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
@@ -306,7 +298,7 @@ mod diagnostics {
306 UnresolvedModule { 298 UnresolvedModule {
307 module: LocalModuleId, 299 module: LocalModuleId,
308 declaration: AstId<ast::Module>, 300 declaration: AstId<ast::Module>,
309 candidate: RelativePathBuf, 301 candidate: String,
310 }, 302 },
311 } 303 }
312 304
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 976e5e585..b8f6aac8f 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -36,8 +36,8 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
36 36
37 // populate external prelude 37 // populate external prelude
38 for dep in &crate_graph[def_map.krate].dependencies { 38 for dep in &crate_graph[def_map.krate].dependencies {
39 let dep_def_map = db.crate_def_map(dep.crate_id);
40 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); 39 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
40 let dep_def_map = db.crate_def_map(dep.crate_id);
41 def_map.extern_prelude.insert( 41 def_map.extern_prelude.insert(
42 dep.as_name(), 42 dep.as_name(),
43 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), 43 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
@@ -825,7 +825,10 @@ impl ModCollector<'_, '_> {
825 let modules = &mut self.def_collector.def_map.modules; 825 let modules = &mut self.def_collector.def_map.modules;
826 let res = modules.alloc(ModuleData::default()); 826 let res = modules.alloc(ModuleData::default());
827 modules[res].parent = Some(self.module_id); 827 modules[res].parent = Some(self.module_id);
828 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); 828 modules[res].origin = match definition {
829 None => ModuleOrigin::Inline { definition: declaration },
830 Some(definition) => ModuleOrigin::File { declaration, definition },
831 };
829 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { 832 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
830 modules[res].scope.define_legacy_macro(name, mac) 833 modules[res].scope.define_legacy_macro(name, mac)
831 } 834 }
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index cede4a6fc..19fe0615a 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -44,7 +44,7 @@ impl ModDir {
44 file_id: HirFileId, 44 file_id: HirFileId,
45 name: &Name, 45 name: &Name,
46 attr_path: Option<&SmolStr>, 46 attr_path: Option<&SmolStr>,
47 ) -> Result<(FileId, ModDir), RelativePathBuf> { 47 ) -> Result<(FileId, ModDir), String> {
48 let file_id = file_id.original_file(db.upcast()); 48 let file_id = file_id.original_file(db.upcast());
49 49
50 let mut candidate_files = Vec::new(); 50 let mut candidate_files = Vec::new();
@@ -52,11 +52,11 @@ impl ModDir {
52 Some(attr_path) => { 52 Some(attr_path) => {
53 let base = 53 let base =
54 if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path }; 54 if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path };
55 candidate_files.push(base.join(attr_path)) 55 candidate_files.push(base.join(attr_path).to_string())
56 } 56 }
57 None => { 57 None => {
58 candidate_files.push(self.path.join(&format!("{}.rs", name))); 58 candidate_files.push(self.path.join(&format!("{}.rs", name)).to_string());
59 candidate_files.push(self.path.join(&format!("{}/mod.rs", name))); 59 candidate_files.push(self.path.join(&format!("{}/mod.rs", name)).to_string());
60 } 60 }
61 }; 61 };
62 62
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index fff257193..5495ce284 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -312,20 +312,16 @@ impl PatStack {
312 Self(v) 312 Self(v)
313 } 313 }
314 314
315 fn is_empty(&self) -> bool {
316 self.0.is_empty()
317 }
318
319 fn head(&self) -> PatIdOrWild {
320 self.0[0]
321 }
322
323 fn get_head(&self) -> Option<PatIdOrWild> { 315 fn get_head(&self) -> Option<PatIdOrWild> {
324 self.0.first().copied() 316 self.0.first().copied()
325 } 317 }
326 318
319 fn tail(&self) -> &[PatIdOrWild] {
320 self.0.get(1..).unwrap_or(&[])
321 }
322
327 fn to_tail(&self) -> PatStack { 323 fn to_tail(&self) -> PatStack {
328 Self::from_slice(&self.0[1..]) 324 Self::from_slice(self.tail())
329 } 325 }
330 326
331 fn replace_head_with<I, T>(&self, pats: I) -> PatStack 327 fn replace_head_with<I, T>(&self, pats: I) -> PatStack
@@ -347,7 +343,7 @@ impl PatStack {
347 /// 343 ///
348 /// See the module docs and the associated documentation in rustc for details. 344 /// See the module docs and the associated documentation in rustc for details.
349 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> { 345 fn specialize_wildcard(&self, cx: &MatchCheckCtx) -> Option<PatStack> {
350 if matches!(self.head().as_pat(cx), Pat::Wild) { 346 if matches!(self.get_head()?.as_pat(cx), Pat::Wild) {
351 Some(self.to_tail()) 347 Some(self.to_tail())
352 } else { 348 } else {
353 None 349 None
@@ -362,7 +358,13 @@ impl PatStack {
362 cx: &MatchCheckCtx, 358 cx: &MatchCheckCtx,
363 constructor: &Constructor, 359 constructor: &Constructor,
364 ) -> MatchCheckResult<Option<PatStack>> { 360 ) -> MatchCheckResult<Option<PatStack>> {
365 let result = match (self.head().as_pat(cx), constructor) { 361 let head = match self.get_head() {
362 Some(head) => head,
363 None => return Ok(None),
364 };
365
366 let head_pat = head.as_pat(cx);
367 let result = match (head_pat, constructor) {
366 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => { 368 (Pat::Tuple { args: ref pat_ids, ellipsis }, Constructor::Tuple { arity: _ }) => {
367 if ellipsis.is_some() { 369 if ellipsis.is_some() {
368 // If there are ellipsis here, we should add the correct number of 370 // If there are ellipsis here, we should add the correct number of
@@ -389,7 +391,7 @@ impl PatStack {
389 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?), 391 (Pat::Wild, constructor) => Some(self.expand_wildcard(cx, constructor)?),
390 (Pat::Path(_), Constructor::Enum(constructor)) => { 392 (Pat::Path(_), Constructor::Enum(constructor)) => {
391 // unit enum variants become `Pat::Path` 393 // unit enum variants become `Pat::Path`
392 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 394 let pat_id = head.as_id().expect("we know this isn't a wild");
393 if !enum_variant_matches(cx, pat_id, *constructor) { 395 if !enum_variant_matches(cx, pat_id, *constructor) {
394 None 396 None
395 } else { 397 } else {
@@ -400,7 +402,7 @@ impl PatStack {
400 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. }, 402 Pat::TupleStruct { args: ref pat_ids, ellipsis, .. },
401 Constructor::Enum(enum_constructor), 403 Constructor::Enum(enum_constructor),
402 ) => { 404 ) => {
403 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 405 let pat_id = head.as_id().expect("we know this isn't a wild");
404 if !enum_variant_matches(cx, pat_id, *enum_constructor) { 406 if !enum_variant_matches(cx, pat_id, *enum_constructor) {
405 None 407 None
406 } else { 408 } else {
@@ -440,7 +442,7 @@ impl PatStack {
440 } 442 }
441 } 443 }
442 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => { 444 (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => {
443 let pat_id = self.head().as_id().expect("we know this isn't a wild"); 445 let pat_id = head.as_id().expect("we know this isn't a wild");
444 if !enum_variant_matches(cx, pat_id, *e) { 446 if !enum_variant_matches(cx, pat_id, *e) {
445 None 447 None
446 } else { 448 } else {
@@ -486,7 +488,7 @@ impl PatStack {
486 ) -> MatchCheckResult<PatStack> { 488 ) -> MatchCheckResult<PatStack> {
487 assert_eq!( 489 assert_eq!(
488 Pat::Wild, 490 Pat::Wild,
489 self.head().as_pat(cx), 491 self.get_head().expect("expand_wildcard called on empty PatStack").as_pat(cx),
490 "expand_wildcard must only be called on PatStack with wild at head", 492 "expand_wildcard must only be called on PatStack with wild at head",
491 ); 493 );
492 494
@@ -504,7 +506,6 @@ impl PatStack {
504 } 506 }
505} 507}
506 508
507#[derive(Debug)]
508/// A collection of PatStack. 509/// A collection of PatStack.
509/// 510///
510/// This type is modeled from the struct of the same name in `rustc`. 511/// This type is modeled from the struct of the same name in `rustc`.
@@ -531,7 +532,7 @@ impl Matrix {
531 } 532 }
532 533
533 fn heads(&self) -> Vec<PatIdOrWild> { 534 fn heads(&self) -> Vec<PatIdOrWild> {
534 self.0.iter().map(|p| p.head()).collect() 535 self.0.iter().flat_map(|p| p.get_head()).collect()
535 } 536 }
536 537
537 /// Computes `D(self)` for each contained PatStack. 538 /// Computes `D(self)` for each contained PatStack.
@@ -618,13 +619,16 @@ pub(crate) fn is_useful(
618 _ => (), 619 _ => (),
619 } 620 }
620 621
621 if v.is_empty() { 622 let head = match v.get_head() {
622 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful }; 623 Some(head) => head,
624 None => {
625 let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
623 626
624 return Ok(result); 627 return Ok(result);
625 } 628 }
629 };
626 630
627 if let Pat::Or(pat_ids) = v.head().as_pat(cx) { 631 if let Pat::Or(pat_ids) = head.as_pat(cx) {
628 let mut found_unimplemented = false; 632 let mut found_unimplemented = false;
629 let any_useful = pat_ids.iter().any(|&pat_id| { 633 let any_useful = pat_ids.iter().any(|&pat_id| {
630 let v = PatStack::from_pattern(pat_id); 634 let v = PatStack::from_pattern(pat_id);
@@ -648,7 +652,7 @@ pub(crate) fn is_useful(
648 }; 652 };
649 } 653 }
650 654
651 if let Some(constructor) = pat_constructor(cx, v.head())? { 655 if let Some(constructor) = pat_constructor(cx, head)? {
652 let matrix = matrix.specialize_constructor(&cx, &constructor)?; 656 let matrix = matrix.specialize_constructor(&cx, &constructor)?;
653 let v = v 657 let v = v
654 .specialize_constructor(&cx, &constructor)? 658 .specialize_constructor(&cx, &constructor)?
@@ -837,194 +841,193 @@ mod tests {
837 841
838 pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB}; 842 pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB};
839 843
840 pub(super) fn check_diagnostic_message(content: &str) -> String { 844 pub(super) fn check_diagnostic_message(ra_fixture: &str) -> String {
841 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().0 845 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().0
842 } 846 }
843 847
844 pub(super) fn check_diagnostic(content: &str) { 848 pub(super) fn check_diagnostic(ra_fixture: &str) {
845 let diagnostic_count = 849 let diagnostic_count =
846 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; 850 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1;
847 851
848 assert_eq!(1, diagnostic_count, "no diagnostic reported"); 852 assert_eq!(1, diagnostic_count, "no diagnostic reported");
849 } 853 }
850 854
851 pub(super) fn check_no_diagnostic(content: &str) { 855 pub(super) fn check_no_diagnostic(ra_fixture: &str) {
852 let diagnostic_count = 856 let (s, diagnostic_count) =
853 TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; 857 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>();
854 858
855 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); 859 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s);
856 } 860 }
857 861
858 #[test] 862 #[test]
859 fn empty_tuple_no_arms_diagnostic_message() { 863 fn empty_tuple_no_arms_diagnostic_message() {
860 let content = r"
861 fn test_fn() {
862 match () {
863 }
864 }
865 ";
866
867 assert_snapshot!( 864 assert_snapshot!(
868 check_diagnostic_message(content), 865 check_diagnostic_message(r"
866 fn test_fn() {
867 match () {
868 }
869 }
870 "),
869 @"\"()\": Missing match arm\n" 871 @"\"()\": Missing match arm\n"
870 ); 872 );
871 } 873 }
872 874
873 #[test] 875 #[test]
874 fn empty_tuple_no_arms() { 876 fn empty_tuple_no_arms() {
875 let content = r" 877 check_diagnostic(
878 r"
876 fn test_fn() { 879 fn test_fn() {
877 match () { 880 match () {
878 } 881 }
879 } 882 }
880 "; 883 ",
881 884 );
882 check_diagnostic(content);
883 } 885 }
884 886
885 #[test] 887 #[test]
886 fn empty_tuple_wild() { 888 fn empty_tuple_wild() {
887 let content = r" 889 check_no_diagnostic(
890 r"
888 fn test_fn() { 891 fn test_fn() {
889 match () { 892 match () {
890 _ => {} 893 _ => {}
891 } 894 }
892 } 895 }
893 "; 896 ",
894 897 );
895 check_no_diagnostic(content);
896 } 898 }
897 899
898 #[test] 900 #[test]
899 fn empty_tuple_no_diagnostic() { 901 fn empty_tuple_no_diagnostic() {
900 let content = r" 902 check_no_diagnostic(
903 r"
901 fn test_fn() { 904 fn test_fn() {
902 match () { 905 match () {
903 () => {} 906 () => {}
904 } 907 }
905 } 908 }
906 "; 909 ",
907 910 );
908 check_no_diagnostic(content);
909 } 911 }
910 912
911 #[test] 913 #[test]
912 fn tuple_of_empty_tuple_no_arms() { 914 fn tuple_of_empty_tuple_no_arms() {
913 let content = r" 915 check_diagnostic(
916 r"
914 fn test_fn() { 917 fn test_fn() {
915 match (()) { 918 match (()) {
916 } 919 }
917 } 920 }
918 "; 921 ",
919 922 );
920 check_diagnostic(content);
921 } 923 }
922 924
923 #[test] 925 #[test]
924 fn tuple_of_empty_tuple_no_diagnostic() { 926 fn tuple_of_empty_tuple_no_diagnostic() {
925 let content = r" 927 check_no_diagnostic(
928 r"
926 fn test_fn() { 929 fn test_fn() {
927 match (()) { 930 match (()) {
928 (()) => {} 931 (()) => {}
929 } 932 }
930 } 933 }
931 "; 934 ",
932 935 );
933 check_no_diagnostic(content);
934 } 936 }
935 937
936 #[test] 938 #[test]
937 fn tuple_of_two_empty_tuple_no_arms() { 939 fn tuple_of_two_empty_tuple_no_arms() {
938 let content = r" 940 check_diagnostic(
941 r"
939 fn test_fn() { 942 fn test_fn() {
940 match ((), ()) { 943 match ((), ()) {
941 } 944 }
942 } 945 }
943 "; 946 ",
944 947 );
945 check_diagnostic(content);
946 } 948 }
947 949
948 #[test] 950 #[test]
949 fn tuple_of_two_empty_tuple_no_diagnostic() { 951 fn tuple_of_two_empty_tuple_no_diagnostic() {
950 let content = r" 952 check_no_diagnostic(
953 r"
951 fn test_fn() { 954 fn test_fn() {
952 match ((), ()) { 955 match ((), ()) {
953 ((), ()) => {} 956 ((), ()) => {}
954 } 957 }
955 } 958 }
956 "; 959 ",
957 960 );
958 check_no_diagnostic(content);
959 } 961 }
960 962
961 #[test] 963 #[test]
962 fn bool_no_arms() { 964 fn bool_no_arms() {
963 let content = r" 965 check_diagnostic(
966 r"
964 fn test_fn() { 967 fn test_fn() {
965 match false { 968 match false {
966 } 969 }
967 } 970 }
968 "; 971 ",
969 972 );
970 check_diagnostic(content);
971 } 973 }
972 974
973 #[test] 975 #[test]
974 fn bool_missing_arm() { 976 fn bool_missing_arm() {
975 let content = r" 977 check_diagnostic(
978 r"
976 fn test_fn() { 979 fn test_fn() {
977 match false { 980 match false {
978 true => {} 981 true => {}
979 } 982 }
980 } 983 }
981 "; 984 ",
982 985 );
983 check_diagnostic(content);
984 } 986 }
985 987
986 #[test] 988 #[test]
987 fn bool_no_diagnostic() { 989 fn bool_no_diagnostic() {
988 let content = r" 990 check_no_diagnostic(
991 r"
989 fn test_fn() { 992 fn test_fn() {
990 match false { 993 match false {
991 true => {} 994 true => {}
992 false => {} 995 false => {}
993 } 996 }
994 } 997 }
995 "; 998 ",
996 999 );
997 check_no_diagnostic(content);
998 } 1000 }
999 1001
1000 #[test] 1002 #[test]
1001 fn tuple_of_bools_no_arms() { 1003 fn tuple_of_bools_no_arms() {
1002 let content = r" 1004 check_diagnostic(
1005 r"
1003 fn test_fn() { 1006 fn test_fn() {
1004 match (false, true) { 1007 match (false, true) {
1005 } 1008 }
1006 } 1009 }
1007 "; 1010 ",
1008 1011 );
1009 check_diagnostic(content);
1010 } 1012 }
1011 1013
1012 #[test] 1014 #[test]
1013 fn tuple_of_bools_missing_arms() { 1015 fn tuple_of_bools_missing_arms() {
1014 let content = r" 1016 check_diagnostic(
1017 r"
1015 fn test_fn() { 1018 fn test_fn() {
1016 match (false, true) { 1019 match (false, true) {
1017 (true, true) => {}, 1020 (true, true) => {},
1018 } 1021 }
1019 } 1022 }
1020 "; 1023 ",
1021 1024 );
1022 check_diagnostic(content);
1023 } 1025 }
1024 1026
1025 #[test] 1027 #[test]
1026 fn tuple_of_bools_missing_arm() { 1028 fn tuple_of_bools_missing_arm() {
1027 let content = r" 1029 check_diagnostic(
1030 r"
1028 fn test_fn() { 1031 fn test_fn() {
1029 match (false, true) { 1032 match (false, true) {
1030 (false, true) => {}, 1033 (false, true) => {},
@@ -1032,14 +1035,14 @@ mod tests {
1032 (true, false) => {}, 1035 (true, false) => {},
1033 } 1036 }
1034 } 1037 }
1035 "; 1038 ",
1036 1039 );
1037 check_diagnostic(content);
1038 } 1040 }
1039 1041
1040 #[test] 1042 #[test]
1041 fn tuple_of_bools_with_wilds() { 1043 fn tuple_of_bools_with_wilds() {
1042 let content = r" 1044 check_no_diagnostic(
1045 r"
1043 fn test_fn() { 1046 fn test_fn() {
1044 match (false, true) { 1047 match (false, true) {
1045 (false, _) => {}, 1048 (false, _) => {},
@@ -1047,14 +1050,14 @@ mod tests {
1047 (_, true) => {}, 1050 (_, true) => {},
1048 } 1051 }
1049 } 1052 }
1050 "; 1053 ",
1051 1054 );
1052 check_no_diagnostic(content);
1053 } 1055 }
1054 1056
1055 #[test] 1057 #[test]
1056 fn tuple_of_bools_no_diagnostic() { 1058 fn tuple_of_bools_no_diagnostic() {
1057 let content = r" 1059 check_no_diagnostic(
1060 r"
1058 fn test_fn() { 1061 fn test_fn() {
1059 match (false, true) { 1062 match (false, true) {
1060 (true, true) => {}, 1063 (true, true) => {},
@@ -1063,27 +1066,27 @@ mod tests {
1063 (false, false) => {}, 1066 (false, false) => {},
1064 } 1067 }
1065 } 1068 }
1066 "; 1069 ",
1067 1070 );
1068 check_no_diagnostic(content);
1069 } 1071 }
1070 1072
1071 #[test] 1073 #[test]
1072 fn tuple_of_bools_binding_missing_arms() { 1074 fn tuple_of_bools_binding_missing_arms() {
1073 let content = r" 1075 check_diagnostic(
1076 r"
1074 fn test_fn() { 1077 fn test_fn() {
1075 match (false, true) { 1078 match (false, true) {
1076 (true, _x) => {}, 1079 (true, _x) => {},
1077 } 1080 }
1078 } 1081 }
1079 "; 1082 ",
1080 1083 );
1081 check_diagnostic(content);
1082 } 1084 }
1083 1085
1084 #[test] 1086 #[test]
1085 fn tuple_of_bools_binding_no_diagnostic() { 1087 fn tuple_of_bools_binding_no_diagnostic() {
1086 let content = r" 1088 check_no_diagnostic(
1089 r"
1087 fn test_fn() { 1090 fn test_fn() {
1088 match (false, true) { 1091 match (false, true) {
1089 (true, _x) => {}, 1092 (true, _x) => {},
@@ -1091,80 +1094,80 @@ mod tests {
1091 (false, false) => {}, 1094 (false, false) => {},
1092 } 1095 }
1093 } 1096 }
1094 "; 1097 ",
1095 1098 );
1096 check_no_diagnostic(content);
1097 } 1099 }
1098 1100
1099 #[test] 1101 #[test]
1100 fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() { 1102 fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() {
1101 let content = r" 1103 check_no_diagnostic(
1104 r"
1102 fn test_fn() { 1105 fn test_fn() {
1103 match (false, true, false) { 1106 match (false, true, false) {
1104 (false, ..) => {}, 1107 (false, ..) => {},
1105 (true, ..) => {}, 1108 (true, ..) => {},
1106 } 1109 }
1107 } 1110 }
1108 "; 1111 ",
1109 1112 );
1110 check_no_diagnostic(content);
1111 } 1113 }
1112 1114
1113 #[test] 1115 #[test]
1114 fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() { 1116 fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() {
1115 let content = r" 1117 check_no_diagnostic(
1118 r"
1116 fn test_fn() { 1119 fn test_fn() {
1117 match (false, true, false) { 1120 match (false, true, false) {
1118 (.., false) => {}, 1121 (.., false) => {},
1119 (.., true) => {}, 1122 (.., true) => {},
1120 } 1123 }
1121 } 1124 }
1122 "; 1125 ",
1123 1126 );
1124 check_no_diagnostic(content);
1125 } 1127 }
1126 1128
1127 #[test] 1129 #[test]
1128 fn tuple_of_bools_with_ellipsis_no_diagnostic() { 1130 fn tuple_of_bools_with_ellipsis_no_diagnostic() {
1129 let content = r" 1131 check_no_diagnostic(
1132 r"
1130 fn test_fn() { 1133 fn test_fn() {
1131 match (false, true, false) { 1134 match (false, true, false) {
1132 (..) => {}, 1135 (..) => {},
1133 } 1136 }
1134 } 1137 }
1135 "; 1138 ",
1136 1139 );
1137 check_no_diagnostic(content);
1138 } 1140 }
1139 1141
1140 #[test] 1142 #[test]
1141 fn tuple_of_tuple_and_bools_no_arms() { 1143 fn tuple_of_tuple_and_bools_no_arms() {
1142 let content = r" 1144 check_diagnostic(
1145 r"
1143 fn test_fn() { 1146 fn test_fn() {
1144 match (false, ((), false)) { 1147 match (false, ((), false)) {
1145 } 1148 }
1146 } 1149 }
1147 "; 1150 ",
1148 1151 );
1149 check_diagnostic(content);
1150 } 1152 }
1151 1153
1152 #[test] 1154 #[test]
1153 fn tuple_of_tuple_and_bools_missing_arms() { 1155 fn tuple_of_tuple_and_bools_missing_arms() {
1154 let content = r" 1156 check_diagnostic(
1157 r"
1155 fn test_fn() { 1158 fn test_fn() {
1156 match (false, ((), false)) { 1159 match (false, ((), false)) {
1157 (true, ((), true)) => {}, 1160 (true, ((), true)) => {},
1158 } 1161 }
1159 } 1162 }
1160 "; 1163 ",
1161 1164 );
1162 check_diagnostic(content);
1163 } 1165 }
1164 1166
1165 #[test] 1167 #[test]
1166 fn tuple_of_tuple_and_bools_no_diagnostic() { 1168 fn tuple_of_tuple_and_bools_no_diagnostic() {
1167 let content = r" 1169 check_no_diagnostic(
1170 r"
1168 fn test_fn() { 1171 fn test_fn() {
1169 match (false, ((), false)) { 1172 match (false, ((), false)) {
1170 (true, ((), true)) => {}, 1173 (true, ((), true)) => {},
@@ -1173,27 +1176,27 @@ mod tests {
1173 (false, ((), false)) => {}, 1176 (false, ((), false)) => {},
1174 } 1177 }
1175 } 1178 }
1176 "; 1179 ",
1177 1180 );
1178 check_no_diagnostic(content);
1179 } 1181 }
1180 1182
1181 #[test] 1183 #[test]
1182 fn tuple_of_tuple_and_bools_wildcard_missing_arms() { 1184 fn tuple_of_tuple_and_bools_wildcard_missing_arms() {
1183 let content = r" 1185 check_diagnostic(
1186 r"
1184 fn test_fn() { 1187 fn test_fn() {
1185 match (false, ((), false)) { 1188 match (false, ((), false)) {
1186 (true, _) => {}, 1189 (true, _) => {},
1187 } 1190 }
1188 } 1191 }
1189 "; 1192 ",
1190 1193 );
1191 check_diagnostic(content);
1192 } 1194 }
1193 1195
1194 #[test] 1196 #[test]
1195 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() { 1197 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() {
1196 let content = r" 1198 check_no_diagnostic(
1199 r"
1197 fn test_fn() { 1200 fn test_fn() {
1198 match (false, ((), false)) { 1201 match (false, ((), false)) {
1199 (true, ((), true)) => {}, 1202 (true, ((), true)) => {},
@@ -1201,14 +1204,14 @@ mod tests {
1201 (false, _) => {}, 1204 (false, _) => {},
1202 } 1205 }
1203 } 1206 }
1204 "; 1207 ",
1205 1208 );
1206 check_no_diagnostic(content);
1207 } 1209 }
1208 1210
1209 #[test] 1211 #[test]
1210 fn enum_no_arms() { 1212 fn enum_no_arms() {
1211 let content = r" 1213 check_diagnostic(
1214 r"
1212 enum Either { 1215 enum Either {
1213 A, 1216 A,
1214 B, 1217 B,
@@ -1217,14 +1220,14 @@ mod tests {
1217 match Either::A { 1220 match Either::A {
1218 } 1221 }
1219 } 1222 }
1220 "; 1223 ",
1221 1224 );
1222 check_diagnostic(content);
1223 } 1225 }
1224 1226
1225 #[test] 1227 #[test]
1226 fn enum_missing_arms() { 1228 fn enum_missing_arms() {
1227 let content = r" 1229 check_diagnostic(
1230 r"
1228 enum Either { 1231 enum Either {
1229 A, 1232 A,
1230 B, 1233 B,
@@ -1234,14 +1237,14 @@ mod tests {
1234 Either::A => {}, 1237 Either::A => {},
1235 } 1238 }
1236 } 1239 }
1237 "; 1240 ",
1238 1241 );
1239 check_diagnostic(content);
1240 } 1242 }
1241 1243
1242 #[test] 1244 #[test]
1243 fn enum_no_diagnostic() { 1245 fn enum_no_diagnostic() {
1244 let content = r" 1246 check_no_diagnostic(
1247 r"
1245 enum Either { 1248 enum Either {
1246 A, 1249 A,
1247 B, 1250 B,
@@ -1252,14 +1255,14 @@ mod tests {
1252 Either::B => {}, 1255 Either::B => {},
1253 } 1256 }
1254 } 1257 }
1255 "; 1258 ",
1256 1259 );
1257 check_no_diagnostic(content);
1258 } 1260 }
1259 1261
1260 #[test] 1262 #[test]
1261 fn enum_ref_missing_arms() { 1263 fn enum_ref_missing_arms() {
1262 let content = r" 1264 check_diagnostic(
1265 r"
1263 enum Either { 1266 enum Either {
1264 A, 1267 A,
1265 B, 1268 B,
@@ -1269,14 +1272,14 @@ mod tests {
1269 Either::A => {}, 1272 Either::A => {},
1270 } 1273 }
1271 } 1274 }
1272 "; 1275 ",
1273 1276 );
1274 check_diagnostic(content);
1275 } 1277 }
1276 1278
1277 #[test] 1279 #[test]
1278 fn enum_ref_no_diagnostic() { 1280 fn enum_ref_no_diagnostic() {
1279 let content = r" 1281 check_no_diagnostic(
1282 r"
1280 enum Either { 1283 enum Either {
1281 A, 1284 A,
1282 B, 1285 B,
@@ -1287,14 +1290,14 @@ mod tests {
1287 Either::B => {}, 1290 Either::B => {},
1288 } 1291 }
1289 } 1292 }
1290 "; 1293 ",
1291 1294 );
1292 check_no_diagnostic(content);
1293 } 1295 }
1294 1296
1295 #[test] 1297 #[test]
1296 fn enum_containing_bool_no_arms() { 1298 fn enum_containing_bool_no_arms() {
1297 let content = r" 1299 check_diagnostic(
1300 r"
1298 enum Either { 1301 enum Either {
1299 A(bool), 1302 A(bool),
1300 B, 1303 B,
@@ -1303,14 +1306,14 @@ mod tests {
1303 match Either::B { 1306 match Either::B {
1304 } 1307 }
1305 } 1308 }
1306 "; 1309 ",
1307 1310 );
1308 check_diagnostic(content);
1309 } 1311 }
1310 1312
1311 #[test] 1313 #[test]
1312 fn enum_containing_bool_missing_arms() { 1314 fn enum_containing_bool_missing_arms() {
1313 let content = r" 1315 check_diagnostic(
1316 r"
1314 enum Either { 1317 enum Either {
1315 A(bool), 1318 A(bool),
1316 B, 1319 B,
@@ -1321,14 +1324,14 @@ mod tests {
1321 Either::B => (), 1324 Either::B => (),
1322 } 1325 }
1323 } 1326 }
1324 "; 1327 ",
1325 1328 );
1326 check_diagnostic(content);
1327 } 1329 }
1328 1330
1329 #[test] 1331 #[test]
1330 fn enum_containing_bool_no_diagnostic() { 1332 fn enum_containing_bool_no_diagnostic() {
1331 let content = r" 1333 check_no_diagnostic(
1334 r"
1332 enum Either { 1335 enum Either {
1333 A(bool), 1336 A(bool),
1334 B, 1337 B,
@@ -1340,14 +1343,14 @@ mod tests {
1340 Either::B => (), 1343 Either::B => (),
1341 } 1344 }
1342 } 1345 }
1343 "; 1346 ",
1344 1347 );
1345 check_no_diagnostic(content);
1346 } 1348 }
1347 1349
1348 #[test] 1350 #[test]
1349 fn enum_containing_bool_with_wild_no_diagnostic() { 1351 fn enum_containing_bool_with_wild_no_diagnostic() {
1350 let content = r" 1352 check_no_diagnostic(
1353 r"
1351 enum Either { 1354 enum Either {
1352 A(bool), 1355 A(bool),
1353 B, 1356 B,
@@ -1358,14 +1361,14 @@ mod tests {
1358 _ => (), 1361 _ => (),
1359 } 1362 }
1360 } 1363 }
1361 "; 1364 ",
1362 1365 );
1363 check_no_diagnostic(content);
1364 } 1366 }
1365 1367
1366 #[test] 1368 #[test]
1367 fn enum_containing_bool_with_wild_2_no_diagnostic() { 1369 fn enum_containing_bool_with_wild_2_no_diagnostic() {
1368 let content = r" 1370 check_no_diagnostic(
1371 r"
1369 enum Either { 1372 enum Either {
1370 A(bool), 1373 A(bool),
1371 B, 1374 B,
@@ -1376,14 +1379,14 @@ mod tests {
1376 Either::B => (), 1379 Either::B => (),
1377 } 1380 }
1378 } 1381 }
1379 "; 1382 ",
1380 1383 );
1381 check_no_diagnostic(content);
1382 } 1384 }
1383 1385
1384 #[test] 1386 #[test]
1385 fn enum_different_sizes_missing_arms() { 1387 fn enum_different_sizes_missing_arms() {
1386 let content = r" 1388 check_diagnostic(
1389 r"
1387 enum Either { 1390 enum Either {
1388 A(bool), 1391 A(bool),
1389 B(bool, bool), 1392 B(bool, bool),
@@ -1394,14 +1397,14 @@ mod tests {
1394 Either::B(false, _) => (), 1397 Either::B(false, _) => (),
1395 } 1398 }
1396 } 1399 }
1397 "; 1400 ",
1398 1401 );
1399 check_diagnostic(content);
1400 } 1402 }
1401 1403
1402 #[test] 1404 #[test]
1403 fn enum_different_sizes_no_diagnostic() { 1405 fn enum_different_sizes_no_diagnostic() {
1404 let content = r" 1406 check_no_diagnostic(
1407 r"
1405 enum Either { 1408 enum Either {
1406 A(bool), 1409 A(bool),
1407 B(bool, bool), 1410 B(bool, bool),
@@ -1413,14 +1416,14 @@ mod tests {
1413 Either::B(false, _) => (), 1416 Either::B(false, _) => (),
1414 } 1417 }
1415 } 1418 }
1416 "; 1419 ",
1417 1420 );
1418 check_no_diagnostic(content);
1419 } 1421 }
1420 1422
1421 #[test] 1423 #[test]
1422 fn or_no_diagnostic() { 1424 fn or_no_diagnostic() {
1423 let content = r" 1425 check_no_diagnostic(
1426 r"
1424 enum Either { 1427 enum Either {
1425 A(bool), 1428 A(bool),
1426 B(bool, bool), 1429 B(bool, bool),
@@ -1432,14 +1435,14 @@ mod tests {
1432 Either::B(false, _) => (), 1435 Either::B(false, _) => (),
1433 } 1436 }
1434 } 1437 }
1435 "; 1438 ",
1436 1439 );
1437 check_no_diagnostic(content);
1438 } 1440 }
1439 1441
1440 #[test] 1442 #[test]
1441 fn tuple_of_enum_no_diagnostic() { 1443 fn tuple_of_enum_no_diagnostic() {
1442 let content = r" 1444 check_no_diagnostic(
1445 r"
1443 enum Either { 1446 enum Either {
1444 A(bool), 1447 A(bool),
1445 B(bool, bool), 1448 B(bool, bool),
@@ -1456,14 +1459,16 @@ mod tests {
1456 (Either::B(_, _), Either2::D) => (), 1459 (Either::B(_, _), Either2::D) => (),
1457 } 1460 }
1458 } 1461 }
1459 "; 1462 ",
1460 1463 );
1461 check_no_diagnostic(content);
1462 } 1464 }
1463 1465
1464 #[test] 1466 #[test]
1465 fn mismatched_types() { 1467 fn mismatched_types() {
1466 let content = r" 1468 // Match statements with arms that don't match the
1469 // expression pattern do not fire this diagnostic.
1470 check_no_diagnostic(
1471 r"
1467 enum Either { 1472 enum Either {
1468 A, 1473 A,
1469 B, 1474 B,
@@ -1478,47 +1483,47 @@ mod tests {
1478 Either2::D => (), 1483 Either2::D => (),
1479 } 1484 }
1480 } 1485 }
1481 "; 1486 ",
1482 1487 );
1483 // Match statements with arms that don't match the
1484 // expression pattern do not fire this diagnostic.
1485 check_no_diagnostic(content);
1486 } 1488 }
1487 1489
1488 #[test] 1490 #[test]
1489 fn mismatched_types_with_different_arity() { 1491 fn mismatched_types_with_different_arity() {
1490 let content = r" 1492 // Match statements with arms that don't match the
1493 // expression pattern do not fire this diagnostic.
1494 check_no_diagnostic(
1495 r"
1491 fn test_fn() { 1496 fn test_fn() {
1492 match (true, false) { 1497 match (true, false) {
1493 (true, false, true) => (), 1498 (true, false, true) => (),
1494 (true) => (), 1499 (true) => (),
1495 } 1500 }
1496 } 1501 }
1497 "; 1502 ",
1498 1503 );
1499 // Match statements with arms that don't match the
1500 // expression pattern do not fire this diagnostic.
1501 check_no_diagnostic(content);
1502 } 1504 }
1503 1505
1504 #[test] 1506 #[test]
1505 fn malformed_match_arm_tuple_missing_pattern() { 1507 fn malformed_match_arm_tuple_missing_pattern() {
1506 let content = r" 1508 // Match statements with arms that don't match the
1509 // expression pattern do not fire this diagnostic.
1510 check_no_diagnostic(
1511 r"
1507 fn test_fn() { 1512 fn test_fn() {
1508 match (0) { 1513 match (0) {
1509 () => (), 1514 () => (),
1510 } 1515 }
1511 } 1516 }
1512 "; 1517 ",
1513 1518 );
1514 // Match statements with arms that don't match the
1515 // expression pattern do not fire this diagnostic.
1516 check_no_diagnostic(content);
1517 } 1519 }
1518 1520
1519 #[test] 1521 #[test]
1520 fn malformed_match_arm_tuple_enum_missing_pattern() { 1522 fn malformed_match_arm_tuple_enum_missing_pattern() {
1521 let content = r" 1523 // We are testing to be sure we don't panic here when the match
1524 // arm `Either::B` is missing its pattern.
1525 check_no_diagnostic(
1526 r"
1522 enum Either { 1527 enum Either {
1523 A, 1528 A,
1524 B(u32), 1529 B(u32),
@@ -1529,32 +1534,30 @@ mod tests {
1529 Either::B() => (), 1534 Either::B() => (),
1530 } 1535 }
1531 } 1536 }
1532 "; 1537 ",
1533 1538 );
1534 // We are testing to be sure we don't panic here when the match
1535 // arm `Either::B` is missing its pattern.
1536 check_no_diagnostic(content);
1537 } 1539 }
1538 1540
1539 #[test] 1541 #[test]
1540 fn enum_not_in_scope() { 1542 fn enum_not_in_scope() {
1541 let content = r" 1543 // The enum is not in scope so we don't perform exhaustiveness
1544 // checking, but we want to be sure we don't panic here (and
1545 // we don't create a diagnostic).
1546 check_no_diagnostic(
1547 r"
1542 fn test_fn() { 1548 fn test_fn() {
1543 match Foo::Bar { 1549 match Foo::Bar {
1544 Foo::Baz => (), 1550 Foo::Baz => (),
1545 } 1551 }
1546 } 1552 }
1547 "; 1553 ",
1548 1554 );
1549 // The enum is not in scope so we don't perform exhaustiveness
1550 // checking, but we want to be sure we don't panic here (and
1551 // we don't create a diagnostic).
1552 check_no_diagnostic(content);
1553 } 1555 }
1554 1556
1555 #[test] 1557 #[test]
1556 fn expr_diverges() { 1558 fn expr_diverges() {
1557 let content = r" 1559 check_no_diagnostic(
1560 r"
1558 enum Either { 1561 enum Either {
1559 A, 1562 A,
1560 B, 1563 B,
@@ -1565,14 +1568,14 @@ mod tests {
1565 Either::B => (), 1568 Either::B => (),
1566 } 1569 }
1567 } 1570 }
1568 "; 1571 ",
1569 1572 );
1570 check_no_diagnostic(content);
1571 } 1573 }
1572 1574
1573 #[test] 1575 #[test]
1574 fn expr_loop_with_break() { 1576 fn expr_loop_with_break() {
1575 let content = r" 1577 check_no_diagnostic(
1578 r"
1576 enum Either { 1579 enum Either {
1577 A, 1580 A,
1578 B, 1581 B,
@@ -1583,14 +1586,14 @@ mod tests {
1583 Either::B => (), 1586 Either::B => (),
1584 } 1587 }
1585 } 1588 }
1586 "; 1589 ",
1587 1590 );
1588 check_no_diagnostic(content);
1589 } 1591 }
1590 1592
1591 #[test] 1593 #[test]
1592 fn expr_partially_diverges() { 1594 fn expr_partially_diverges() {
1593 let content = r" 1595 check_no_diagnostic(
1596 r"
1594 enum Either<T> { 1597 enum Either<T> {
1595 A(T), 1598 A(T),
1596 B, 1599 B,
@@ -1604,14 +1607,14 @@ mod tests {
1604 Either::B => 0, 1607 Either::B => 0,
1605 } 1608 }
1606 } 1609 }
1607 "; 1610 ",
1608 1611 );
1609 check_no_diagnostic(content);
1610 } 1612 }
1611 1613
1612 #[test] 1614 #[test]
1613 fn enum_record_no_arms() { 1615 fn enum_record_no_arms() {
1614 let content = r" 1616 check_diagnostic(
1617 r"
1615 enum Either { 1618 enum Either {
1616 A { foo: bool }, 1619 A { foo: bool },
1617 B, 1620 B,
@@ -1621,14 +1624,14 @@ mod tests {
1621 match a { 1624 match a {
1622 } 1625 }
1623 } 1626 }
1624 "; 1627 ",
1625 1628 );
1626 check_diagnostic(content);
1627 } 1629 }
1628 1630
1629 #[test] 1631 #[test]
1630 fn enum_record_missing_arms() { 1632 fn enum_record_missing_arms() {
1631 let content = r" 1633 check_diagnostic(
1634 r"
1632 enum Either { 1635 enum Either {
1633 A { foo: bool }, 1636 A { foo: bool },
1634 B, 1637 B,
@@ -1639,14 +1642,14 @@ mod tests {
1639 Either::A { foo: true } => (), 1642 Either::A { foo: true } => (),
1640 } 1643 }
1641 } 1644 }
1642 "; 1645 ",
1643 1646 );
1644 check_diagnostic(content);
1645 } 1647 }
1646 1648
1647 #[test] 1649 #[test]
1648 fn enum_record_no_diagnostic() { 1650 fn enum_record_no_diagnostic() {
1649 let content = r" 1651 check_no_diagnostic(
1652 r"
1650 enum Either { 1653 enum Either {
1651 A { foo: bool }, 1654 A { foo: bool },
1652 B, 1655 B,
@@ -1659,14 +1662,17 @@ mod tests {
1659 Either::B => (), 1662 Either::B => (),
1660 } 1663 }
1661 } 1664 }
1662 "; 1665 ",
1663 1666 );
1664 check_no_diagnostic(content);
1665 } 1667 }
1666 1668
1667 #[test] 1669 #[test]
1668 fn enum_record_missing_field_no_diagnostic() { 1670 fn enum_record_missing_field_no_diagnostic() {
1669 let content = r" 1671 // When `Either::A` is missing a struct member, we don't want
1672 // to fire the missing match arm diagnostic. This should fire
1673 // some other diagnostic.
1674 check_no_diagnostic(
1675 r"
1670 enum Either { 1676 enum Either {
1671 A { foo: bool }, 1677 A { foo: bool },
1672 B, 1678 B,
@@ -1678,17 +1684,16 @@ mod tests {
1678 Either::B => (), 1684 Either::B => (),
1679 } 1685 }
1680 } 1686 }
1681 "; 1687 ",
1682 1688 );
1683 // When `Either::A` is missing a struct member, we don't want
1684 // to fire the missing match arm diagnostic. This should fire
1685 // some other diagnostic.
1686 check_no_diagnostic(content);
1687 } 1689 }
1688 1690
1689 #[test] 1691 #[test]
1690 fn enum_record_missing_field_missing_match_arm() { 1692 fn enum_record_missing_field_missing_match_arm() {
1691 let content = r" 1693 // Even though `Either::A` is missing fields, we still want to fire
1694 // the missing arm diagnostic here, since we know `Either::B` is missing.
1695 check_diagnostic(
1696 r"
1692 enum Either { 1697 enum Either {
1693 A { foo: bool }, 1698 A { foo: bool },
1694 B, 1699 B,
@@ -1699,16 +1704,14 @@ mod tests {
1699 Either::A { } => (), 1704 Either::A { } => (),
1700 } 1705 }
1701 } 1706 }
1702 "; 1707 ",
1703 1708 );
1704 // Even though `Either::A` is missing fields, we still want to fire
1705 // the missing arm diagnostic here, since we know `Either::B` is missing.
1706 check_diagnostic(content);
1707 } 1709 }
1708 1710
1709 #[test] 1711 #[test]
1710 fn enum_record_no_diagnostic_wild() { 1712 fn enum_record_no_diagnostic_wild() {
1711 let content = r" 1713 check_no_diagnostic(
1714 r"
1712 enum Either { 1715 enum Either {
1713 A { foo: bool }, 1716 A { foo: bool },
1714 B, 1717 B,
@@ -1720,14 +1723,14 @@ mod tests {
1720 Either::B => (), 1723 Either::B => (),
1721 } 1724 }
1722 } 1725 }
1723 "; 1726 ",
1724 1727 );
1725 check_no_diagnostic(content);
1726 } 1728 }
1727 1729
1728 #[test] 1730 #[test]
1729 fn enum_record_fields_out_of_order_missing_arm() { 1731 fn enum_record_fields_out_of_order_missing_arm() {
1730 let content = r" 1732 check_diagnostic(
1733 r"
1731 enum Either { 1734 enum Either {
1732 A { foo: bool, bar: () }, 1735 A { foo: bool, bar: () },
1733 B, 1736 B,
@@ -1739,14 +1742,14 @@ mod tests {
1739 Either::A { foo: true, bar: () } => (), 1742 Either::A { foo: true, bar: () } => (),
1740 } 1743 }
1741 } 1744 }
1742 "; 1745 ",
1743 1746 );
1744 check_diagnostic(content);
1745 } 1747 }
1746 1748
1747 #[test] 1749 #[test]
1748 fn enum_record_fields_out_of_order_no_diagnostic() { 1750 fn enum_record_fields_out_of_order_no_diagnostic() {
1749 let content = r" 1751 check_no_diagnostic(
1752 r"
1750 enum Either { 1753 enum Either {
1751 A { foo: bool, bar: () }, 1754 A { foo: bool, bar: () },
1752 B, 1755 B,
@@ -1759,89 +1762,89 @@ mod tests {
1759 Either::B => (), 1762 Either::B => (),
1760 } 1763 }
1761 } 1764 }
1762 "; 1765 ",
1763 1766 );
1764 check_no_diagnostic(content);
1765 } 1767 }
1766 1768
1767 #[test] 1769 #[test]
1768 fn enum_record_ellipsis_missing_arm() { 1770 fn enum_record_ellipsis_missing_arm() {
1769 let content = r" 1771 check_diagnostic(
1770 enum Either { 1772 r"
1771 A { foo: bool, bar: bool }, 1773 enum Either {
1772 B, 1774 A { foo: bool, bar: bool },
1773 } 1775 B,
1774 fn test_fn() { 1776 }
1775 match Either::B { 1777 fn test_fn() {
1776 Either::A { foo: true, .. } => (), 1778 match Either::B {
1777 Either::B => (), 1779 Either::A { foo: true, .. } => (),
1778 } 1780 Either::B => (),
1779 } 1781 }
1780 "; 1782 }
1781 1783 ",
1782 check_diagnostic(content); 1784 );
1783 } 1785 }
1784 1786
1785 #[test] 1787 #[test]
1786 fn enum_record_ellipsis_no_diagnostic() { 1788 fn enum_record_ellipsis_no_diagnostic() {
1787 let content = r" 1789 check_no_diagnostic(
1788 enum Either { 1790 r"
1789 A { foo: bool, bar: bool }, 1791 enum Either {
1790 B, 1792 A { foo: bool, bar: bool },
1791 } 1793 B,
1792 fn test_fn() { 1794 }
1793 let a = Either::A { foo: true }; 1795 fn test_fn() {
1794 match a { 1796 let a = Either::A { foo: true };
1795 Either::A { foo: true, .. } => (), 1797 match a {
1796 Either::A { foo: false, .. } => (), 1798 Either::A { foo: true, .. } => (),
1797 Either::B => (), 1799 Either::A { foo: false, .. } => (),
1798 } 1800 Either::B => (),
1799 } 1801 }
1800 "; 1802 }
1801 1803 ",
1802 check_no_diagnostic(content); 1804 );
1803 } 1805 }
1804 1806
1805 #[test] 1807 #[test]
1806 fn enum_record_ellipsis_all_fields_missing_arm() { 1808 fn enum_record_ellipsis_all_fields_missing_arm() {
1807 let content = r" 1809 check_diagnostic(
1808 enum Either { 1810 r"
1809 A { foo: bool, bar: bool }, 1811 enum Either {
1810 B, 1812 A { foo: bool, bar: bool },
1811 } 1813 B,
1812 fn test_fn() { 1814 }
1813 let a = Either::B; 1815 fn test_fn() {
1814 match a { 1816 let a = Either::B;
1815 Either::A { .. } => (), 1817 match a {
1816 } 1818 Either::A { .. } => (),
1817 } 1819 }
1818 "; 1820 }
1819 1821 ",
1820 check_diagnostic(content); 1822 );
1821 } 1823 }
1822 1824
1823 #[test] 1825 #[test]
1824 fn enum_record_ellipsis_all_fields_no_diagnostic() { 1826 fn enum_record_ellipsis_all_fields_no_diagnostic() {
1825 let content = r" 1827 check_no_diagnostic(
1826 enum Either { 1828 r"
1827 A { foo: bool, bar: bool }, 1829 enum Either {
1828 B, 1830 A { foo: bool, bar: bool },
1829 } 1831 B,
1830 fn test_fn() { 1832 }
1831 let a = Either::B; 1833 fn test_fn() {
1832 match a { 1834 let a = Either::B;
1833 Either::A { .. } => (), 1835 match a {
1834 Either::B => (), 1836 Either::A { .. } => (),
1835 } 1837 Either::B => (),
1836 } 1838 }
1837 "; 1839 }
1838 1840 ",
1839 check_no_diagnostic(content); 1841 );
1840 } 1842 }
1841 1843
1842 #[test] 1844 #[test]
1843 fn enum_tuple_partial_ellipsis_no_diagnostic() { 1845 fn enum_tuple_partial_ellipsis_no_diagnostic() {
1844 let content = r" 1846 check_no_diagnostic(
1847 r"
1845 enum Either { 1848 enum Either {
1846 A(bool, bool, bool, bool), 1849 A(bool, bool, bool, bool),
1847 B, 1850 B,
@@ -1855,14 +1858,14 @@ mod tests {
1855 Either::B => {}, 1858 Either::B => {},
1856 } 1859 }
1857 } 1860 }
1858 "; 1861 ",
1859 1862 );
1860 check_no_diagnostic(content);
1861 } 1863 }
1862 1864
1863 #[test] 1865 #[test]
1864 fn enum_tuple_partial_ellipsis_2_no_diagnostic() { 1866 fn enum_tuple_partial_ellipsis_2_no_diagnostic() {
1865 let content = r" 1867 check_no_diagnostic(
1868 r"
1866 enum Either { 1869 enum Either {
1867 A(bool, bool, bool, bool), 1870 A(bool, bool, bool, bool),
1868 B, 1871 B,
@@ -1876,14 +1879,14 @@ mod tests {
1876 Either::B => {}, 1879 Either::B => {},
1877 } 1880 }
1878 } 1881 }
1879 "; 1882 ",
1880 1883 );
1881 check_no_diagnostic(content);
1882 } 1884 }
1883 1885
1884 #[test] 1886 #[test]
1885 fn enum_tuple_partial_ellipsis_missing_arm() { 1887 fn enum_tuple_partial_ellipsis_missing_arm() {
1886 let content = r" 1888 check_diagnostic(
1889 r"
1887 enum Either { 1890 enum Either {
1888 A(bool, bool, bool, bool), 1891 A(bool, bool, bool, bool),
1889 B, 1892 B,
@@ -1896,14 +1899,14 @@ mod tests {
1896 Either::B => {}, 1899 Either::B => {},
1897 } 1900 }
1898 } 1901 }
1899 "; 1902 ",
1900 1903 );
1901 check_diagnostic(content);
1902 } 1904 }
1903 1905
1904 #[test] 1906 #[test]
1905 fn enum_tuple_partial_ellipsis_2_missing_arm() { 1907 fn enum_tuple_partial_ellipsis_2_missing_arm() {
1906 let content = r" 1908 check_diagnostic(
1909 r"
1907 enum Either { 1910 enum Either {
1908 A(bool, bool, bool, bool), 1911 A(bool, bool, bool, bool),
1909 B, 1912 B,
@@ -1916,14 +1919,14 @@ mod tests {
1916 Either::B => {}, 1919 Either::B => {},
1917 } 1920 }
1918 } 1921 }
1919 "; 1922 ",
1920 1923 );
1921 check_diagnostic(content);
1922 } 1924 }
1923 1925
1924 #[test] 1926 #[test]
1925 fn enum_tuple_ellipsis_no_diagnostic() { 1927 fn enum_tuple_ellipsis_no_diagnostic() {
1926 let content = r" 1928 check_no_diagnostic(
1929 r"
1927 enum Either { 1930 enum Either {
1928 A(bool, bool, bool, bool), 1931 A(bool, bool, bool, bool),
1929 B, 1932 B,
@@ -1934,51 +1937,51 @@ mod tests {
1934 Either::B => {}, 1937 Either::B => {},
1935 } 1938 }
1936 } 1939 }
1937 "; 1940 ",
1938 1941 );
1939 check_no_diagnostic(content);
1940 } 1942 }
1941 1943
1942 #[test] 1944 #[test]
1943 fn enum_never() { 1945 fn enum_never() {
1944 let content = r" 1946 check_no_diagnostic(
1947 r"
1945 enum Never {} 1948 enum Never {}
1946 1949
1947 fn test_fn(never: Never) { 1950 fn test_fn(never: Never) {
1948 match never {} 1951 match never {}
1949 } 1952 }
1950 "; 1953 ",
1951 1954 );
1952 check_no_diagnostic(content);
1953 } 1955 }
1954 1956
1955 #[test] 1957 #[test]
1956 fn type_never() { 1958 fn type_never() {
1957 let content = r" 1959 check_no_diagnostic(
1960 r"
1958 fn test_fn(never: !) { 1961 fn test_fn(never: !) {
1959 match never {} 1962 match never {}
1960 } 1963 }
1961 "; 1964 ",
1962 1965 );
1963 check_no_diagnostic(content);
1964 } 1966 }
1965 1967
1966 #[test] 1968 #[test]
1967 fn enum_never_ref() { 1969 fn enum_never_ref() {
1968 let content = r" 1970 check_no_diagnostic(
1971 r"
1969 enum Never {} 1972 enum Never {}
1970 1973
1971 fn test_fn(never: &Never) { 1974 fn test_fn(never: &Never) {
1972 match never {} 1975 match never {}
1973 } 1976 }
1974 "; 1977 ",
1975 1978 );
1976 check_no_diagnostic(content);
1977 } 1979 }
1978 1980
1979 #[test] 1981 #[test]
1980 fn expr_diverges_missing_arm() { 1982 fn expr_diverges_missing_arm() {
1981 let content = r" 1983 check_no_diagnostic(
1984 r"
1982 enum Either { 1985 enum Either {
1983 A, 1986 A,
1984 B, 1987 B,
@@ -1988,9 +1991,49 @@ mod tests {
1988 Either::A => (), 1991 Either::A => (),
1989 } 1992 }
1990 } 1993 }
1991 "; 1994 ",
1995 );
1996 }
1992 1997
1993 check_no_diagnostic(content); 1998 #[test]
1999 fn or_pattern_panic() {
2000 check_no_diagnostic(
2001 r"
2002 pub enum Category {
2003 Infinity,
2004 Zero,
2005 }
2006
2007 fn panic(a: Category, b: Category) {
2008 match (a, b) {
2009 (Category::Zero | Category::Infinity, _) => {}
2010 (_, Category::Zero | Category::Infinity) => {}
2011 }
2012 }
2013 ",
2014 );
2015 }
2016
2017 #[test]
2018 fn or_pattern_panic_2() {
2019 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
2020 // so this acts as a regression test for that.
2021 check_diagnostic(
2022 r"
2023 pub enum Category {
2024 Infinity,
2025 Zero,
2026 }
2027
2028 fn panic(a: Category, b: Category) {
2029 match (a, b) {
2030 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {}
2031
2032 (Category::Infinity | Category::Zero, _) => {}
2033 }
2034 }
2035 ",
2036 );
1994 } 2037 }
1995} 2038}
1996 2039
@@ -2010,23 +2053,26 @@ mod false_negatives {
2010 2053
2011 #[test] 2054 #[test]
2012 fn integers() { 2055 fn integers() {
2013 let content = r" 2056 // This is a false negative.
2057 // We don't currently check integer exhaustiveness.
2058 check_no_diagnostic(
2059 r"
2014 fn test_fn() { 2060 fn test_fn() {
2015 match 5 { 2061 match 5 {
2016 10 => (), 2062 10 => (),
2017 11..20 => (), 2063 11..20 => (),
2018 } 2064 }
2019 } 2065 }
2020 "; 2066 ",
2021 2067 );
2022 // This is a false negative.
2023 // We don't currently check integer exhaustiveness.
2024 check_no_diagnostic(content);
2025 } 2068 }
2026 2069
2027 #[test] 2070 #[test]
2028 fn internal_or() { 2071 fn internal_or() {
2029 let content = r" 2072 // This is a false negative.
2073 // We do not currently handle patterns with internal `or`s.
2074 check_no_diagnostic(
2075 r"
2030 fn test_fn() { 2076 fn test_fn() {
2031 enum Either { 2077 enum Either {
2032 A(bool), 2078 A(bool),
@@ -2036,16 +2082,18 @@ mod false_negatives {
2036 Either::A(true | false) => (), 2082 Either::A(true | false) => (),
2037 } 2083 }
2038 } 2084 }
2039 "; 2085 ",
2040 2086 );
2041 // This is a false negative.
2042 // We do not currently handle patterns with internal `or`s.
2043 check_no_diagnostic(content);
2044 } 2087 }
2045 2088
2046 #[test] 2089 #[test]
2047 fn expr_loop_missing_arm() { 2090 fn expr_loop_missing_arm() {
2048 let content = r" 2091 // This is a false negative.
2092 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2093 // causes us to skip the diagnostic since `Either::A` doesn't type check
2094 // with `!`.
2095 check_diagnostic(
2096 r"
2049 enum Either { 2097 enum Either {
2050 A, 2098 A,
2051 B, 2099 B,
@@ -2055,48 +2103,46 @@ mod false_negatives {
2055 Either::A => (), 2103 Either::A => (),
2056 } 2104 }
2057 } 2105 }
2058 "; 2106 ",
2059 2107 );
2060 // This is a false negative.
2061 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2062 // causes us to skip the diagnostic since `Either::A` doesn't type check
2063 // with `!`.
2064 check_diagnostic(content);
2065 } 2108 }
2066 2109
2067 #[test] 2110 #[test]
2068 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { 2111 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
2069 let content = r" 2112 // This is a false negative.
2113 // We don't currently handle tuple patterns with ellipsis.
2114 check_no_diagnostic(
2115 r"
2070 fn test_fn() { 2116 fn test_fn() {
2071 match (false, true, false) { 2117 match (false, true, false) {
2072 (false, ..) => {}, 2118 (false, ..) => {},
2073 } 2119 }
2074 } 2120 }
2075 "; 2121 ",
2076 2122 );
2077 // This is a false negative.
2078 // We don't currently handle tuple patterns with ellipsis.
2079 check_no_diagnostic(content);
2080 } 2123 }
2081 2124
2082 #[test] 2125 #[test]
2083 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { 2126 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() {
2084 let content = r" 2127 // This is a false negative.
2128 // We don't currently handle tuple patterns with ellipsis.
2129 check_no_diagnostic(
2130 r"
2085 fn test_fn() { 2131 fn test_fn() {
2086 match (false, true, false) { 2132 match (false, true, false) {
2087 (.., false) => {}, 2133 (.., false) => {},
2088 } 2134 }
2089 } 2135 }
2090 "; 2136 ",
2091 2137 );
2092 // This is a false negative.
2093 // We don't currently handle tuple patterns with ellipsis.
2094 check_no_diagnostic(content);
2095 } 2138 }
2096 2139
2097 #[test] 2140 #[test]
2098 fn struct_missing_arm() { 2141 fn struct_missing_arm() {
2099 let content = r" 2142 // This is a false negative.
2143 // We don't currently handle structs.
2144 check_no_diagnostic(
2145 r"
2100 struct Foo { 2146 struct Foo {
2101 a: bool, 2147 a: bool,
2102 } 2148 }
@@ -2105,10 +2151,7 @@ mod false_negatives {
2105 Foo { a: true } => {}, 2151 Foo { a: true } => {},
2106 } 2152 }
2107 } 2153 }
2108 "; 2154 ",
2109 2155 );
2110 // This is a false negative.
2111 // We don't currently handle structs.
2112 check_no_diagnostic(content);
2113 } 2156 }
2114} 2157}
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index bf71d38d6..7889b8d2c 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,15 +3,15 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId, 6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId,
7 TypeParamId, VariantId, 7 VariantId,
8}; 8};
9use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
10use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; 10use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
11use ra_prof::profile; 11use ra_prof::profile;
12 12
13use crate::{