aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml37
-rw-r--r--Cargo.lock169
-rw-r--r--crates/assists/src/handlers/introduce_named_lifetime.rs2
-rw-r--r--crates/completion/src/completions/keyword.rs2
-rw-r--r--crates/completion/src/item.rs4
-rw-r--r--crates/hir_def/Cargo.toml2
-rw-r--r--crates/hir_def/src/adt.rs2
-rw-r--r--crates/hir_def/src/attr.rs2
-rw-r--r--crates/hir_def/src/body.rs2
-rw-r--r--crates/hir_def/src/db.rs2
-rw-r--r--crates/hir_def/src/expr.rs4
-rw-r--r--crates/hir_def/src/generics.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs12
-rw-r--r--crates/hir_def/src/item_tree/lower.rs4
-rw-r--r--crates/hir_def/src/path.rs2
-rw-r--r--crates/hir_def/src/src.rs2
-rw-r--r--crates/hir_def/src/trace.rs4
-rw-r--r--crates/hir_def/src/type_ref.rs2
-rw-r--r--crates/hir_expand/Cargo.toml2
-rw-r--r--crates/hir_expand/src/ast_id_map.rs30
-rw-r--r--crates/hir_expand/src/hygiene.rs2
-rw-r--r--crates/hir_expand/src/proc_macro.rs4
-rw-r--r--crates/hir_ty/Cargo.toml2
-rw-r--r--crates/hir_ty/src/db.rs2
-rw-r--r--crates/hir_ty/src/infer.rs2
-rw-r--r--crates/hir_ty/src/lower.rs2
-rw-r--r--crates/hir_ty/src/tests.rs4
-rw-r--r--crates/ide/src/diagnostics/fixes.rs2
-rw-r--r--crates/ide/src/display/navigation_target.rs14
-rw-r--r--crates/ide/src/goto_definition.rs5
-rw-r--r--crates/ide/src/hover.rs5
-rw-r--r--crates/ide/src/lib.rs15
-rw-r--r--crates/ide/src/references.rs20
-rw-r--r--crates/ide/src/references/rename.rs676
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs22
-rw-r--r--crates/ide/src/syntax_tree.rs28
-rw-r--r--crates/ide_db/src/defs.rs11
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs2
-rw-r--r--crates/mbe/src/syntax_bridge.rs4
-rw-r--r--crates/mbe/src/tests.rs10
-rw-r--r--crates/parser/src/grammar.rs12
-rw-r--r--crates/parser/src/grammar/items.rs2
-rw-r--r--crates/parser/src/grammar/items/traits.rs4
-rw-r--r--crates/parser/src/grammar/params.rs31
-rw-r--r--crates/parser/src/syntax_kind.rs3
-rw-r--r--crates/parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/proc_macro_api/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt8
-rw-r--r--crates/proc_macro_srv/src/tests/mod.rs8
-rw-r--r--crates/proc_macro_srv/src/tests/utils.rs2
-rw-r--r--crates/profile/Cargo.toml4
-rw-r--r--crates/profile/src/memory_usage.rs7
-rw-r--r--crates/project_model/Cargo.toml3
-rw-r--r--crates/project_model/src/lib.rs1
-rw-r--r--crates/project_model/src/rustc_cfg.rs34
-rw-r--r--crates/project_model/src/workspace.rs121
-rw-r--r--crates/rust-analyzer/Cargo.toml6
-rw-r--r--crates/rust-analyzer/src/bin/main.rs4
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs2
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
-rw-r--r--crates/rust-analyzer/src/reload.rs16
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs40
-rw-r--r--crates/syntax/src/ast/node_ext.rs33
-rw-r--r--crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast10
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0006_self_param.rast15
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rast42
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rast24
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0007_extern_crate.rast3
-rw-r--r--crates/syntax/test_data/parser/ok/0012_visibility.rast10
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast3
-rw-r--r--crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast24
-rw-r--r--editors/code/src/main.ts1
-rw-r--r--lib/arena/Cargo.toml2
-rw-r--r--lib/arena/src/lib.rs61
-rw-r--r--lib/arena/src/map.rs39
-rw-r--r--xtask/Cargo.toml2
-rw-r--r--xtask/src/ast_src.rs1
-rw-r--r--xtask/src/install.rs2
-rw-r--r--xtask/src/main.rs12
87 files changed, 1073 insertions, 714 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index ece1fd364..a97ed24ba 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -118,6 +118,37 @@ jobs:
118 name: dist-x86_64-unknown-linux-gnu 118 name: dist-x86_64-unknown-linux-gnu
119 path: ./dist 119 path: ./dist
120 120
121 dist-aarch64-unknown-linux-gnu:
122 name: dist (aarch64-unknown-linux-gnu)
123 runs-on: ubuntu-16.04
124 env:
125 RA_TARGET: aarch64-unknown-linux-gnu
126 CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
127
128 steps:
129 - name: Checkout repository
130 uses: actions/checkout@v2
131
132 - name: Install Rust toolchain
133 uses: actions-rs/toolchain@v1
134 with:
135 toolchain: stable
136 target: aarch64-unknown-linux-gnu
137 profile: minimal
138 override: true
139
140 - name: Install target toolchain
141 run: sudo apt-get install gcc-aarch64-linux-gnu
142
143 - name: Dist
144 run: cargo xtask dist
145
146 - name: Upload artifacts
147 uses: actions/upload-artifact@v1
148 with:
149 name: dist-aarch64-unknown-linux-gnu
150 path: ./dist
151
121 dist-x86_64-apple-darwin: 152 dist-x86_64-apple-darwin:
122 name: dist (x86_64-apple-darwin) 153 name: dist (x86_64-apple-darwin)
123 runs-on: macos-latest 154 runs-on: macos-latest
@@ -174,7 +205,7 @@ jobs:
174 publish: 205 publish:
175 name: publish 206 name: publish
176 runs-on: ubuntu-16.04 207 runs-on: ubuntu-16.04
177 needs: ['dist-x86_64-pc-windows-msvc', 'dist-aarch64-pc-windows-msvc', 'dist-x86_64-unknown-linux-gnu', 'dist-x86_64-apple-darwin', 'dist-aarch64-apple-darwin'] 208 needs: ['dist-x86_64-pc-windows-msvc', 'dist-aarch64-pc-windows-msvc', 'dist-x86_64-unknown-linux-gnu', 'dist-aarch64-unknown-linux-gnu', 'dist-x86_64-apple-darwin', 'dist-aarch64-apple-darwin']
178 steps: 209 steps:
179 - name: Install Nodejs 210 - name: Install Nodejs
180 uses: actions/setup-node@v1 211 uses: actions/setup-node@v1
@@ -207,6 +238,10 @@ jobs:
207 path: dist 238 path: dist
208 - uses: actions/download-artifact@v1 239 - uses: actions/download-artifact@v1
209 with: 240 with:
241 name: dist-aarch64-unknown-linux-gnu
242 path: dist
243 - uses: actions/download-artifact@v1
244 with:
210 name: dist-x86_64-pc-windows-msvc 245 name: dist-x86_64-pc-windows-msvc
211 path: dist 246 path: dist
212 - uses: actions/download-artifact@v1 247 - uses: actions/download-artifact@v1
diff --git a/Cargo.lock b/Cargo.lock
index db8b49122..f01544324 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,9 +26,9 @@ dependencies = [
26 26
27[[package]] 27[[package]]
28name = "anyhow" 28name = "anyhow"
29version = "1.0.37" 29version = "1.0.38"
30source = "registry+https://github.com/rust-lang/crates.io-index" 30source = "registry+https://github.com/rust-lang/crates.io-index"
31checksum = "ee67c11feeac938fae061b232e38e0b6d94f97a9df10e6271319325ac4c56a86" 31checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
32 32
33[[package]] 33[[package]]
34name = "anymap" 34name = "anymap"
@@ -118,9 +118,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
118 118
119[[package]] 119[[package]]
120name = "byteorder" 120name = "byteorder"
121version = "1.3.4" 121version = "1.4.2"
122source = "registry+https://github.com/rust-lang/crates.io-index" 122source = "registry+https://github.com/rust-lang/crates.io-index"
123checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 123checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
124 124
125[[package]] 125[[package]]
126name = "cargo-platform" 126name = "cargo-platform"
@@ -133,9 +133,9 @@ dependencies = [
133 133
134[[package]] 134[[package]]
135name = "cargo_metadata" 135name = "cargo_metadata"
136version = "0.12.2" 136version = "0.12.3"
137source = "registry+https://github.com/rust-lang/crates.io-index" 137source = "registry+https://github.com/rust-lang/crates.io-index"
138checksum = "11a47b6286279a9998588ef7050d1ebc2500c69892a557c90fe5d071c64415dc" 138checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f"
139dependencies = [ 139dependencies = [
140 "cargo-platform", 140 "cargo-platform",
141 "semver", 141 "semver",
@@ -269,9 +269,9 @@ dependencies = [
269 269
270[[package]] 270[[package]]
271name = "const_fn" 271name = "const_fn"
272version = "0.4.4" 272version = "0.4.5"
273source = "registry+https://github.com/rust-lang/crates.io-index" 273source = "registry+https://github.com/rust-lang/crates.io-index"
274checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" 274checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
275 275
276[[package]] 276[[package]]
277name = "crc32fast" 277name = "crc32fast"
@@ -449,6 +449,12 @@ dependencies = [
449] 449]
450 450
451[[package]] 451[[package]]
452name = "fs_extra"
453version = "1.2.0"
454source = "registry+https://github.com/rust-lang/crates.io-index"
455checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
456
457[[package]]
452name = "fsevent" 458name = "fsevent"
453version = "2.0.2" 459version = "2.0.2"
454source = "registry+https://github.com/rust-lang/crates.io-index" 460source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -502,6 +508,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
502checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 508checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
503 509
504[[package]] 510[[package]]
511name = "hashbrown"
512version = "0.10.0"
513source = "registry+https://github.com/rust-lang/crates.io-index"
514checksum = "2140e9c963869f01789fa4fef4805211081ec794af5fc77c0d5b377906118853"
515
516[[package]]
505name = "heck" 517name = "heck"
506version = "0.3.2" 518version = "0.3.2"
507source = "registry+https://github.com/rust-lang/crates.io-index" 519source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -512,9 +524,9 @@ dependencies = [
512 524
513[[package]] 525[[package]]
514name = "hermit-abi" 526name = "hermit-abi"
515version = "0.1.17" 527version = "0.1.18"
516source = "registry+https://github.com/rust-lang/crates.io-index" 528source = "registry+https://github.com/rust-lang/crates.io-index"
517checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" 529checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
518dependencies = [ 530dependencies = [
519 "libc", 531 "libc",
520] 532]
@@ -552,7 +564,7 @@ dependencies = [
552 "hir_expand", 564 "hir_expand",
553 "indexmap", 565 "indexmap",
554 "itertools 0.10.0", 566 "itertools 0.10.0",
555 "la-arena 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 567 "la-arena",
556 "log", 568 "log",
557 "mbe", 569 "mbe",
558 "once_cell", 570 "once_cell",
@@ -571,7 +583,7 @@ version = "0.0.0"
571dependencies = [ 583dependencies = [
572 "base_db", 584 "base_db",
573 "either", 585 "either",
574 "la-arena 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 586 "la-arena",
575 "log", 587 "log",
576 "mbe", 588 "mbe",
577 "parser", 589 "parser",
@@ -596,7 +608,7 @@ dependencies = [
596 "hir_def", 608 "hir_def",
597 "hir_expand", 609 "hir_expand",
598 "itertools 0.10.0", 610 "itertools 0.10.0",
599 "la-arena 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 611 "la-arena",
600 "log", 612 "log",
601 "once_cell", 613 "once_cell",
602 "profile", 614 "profile",
@@ -686,7 +698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
686checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" 698checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
687dependencies = [ 699dependencies = [
688 "autocfg", 700 "autocfg",
689 "hashbrown", 701 "hashbrown 0.9.1",
690] 702]
691 703
692[[package]] 704[[package]]
@@ -702,9 +714,9 @@ dependencies = [
702 714
703[[package]] 715[[package]]
704name = "inotify-sys" 716name = "inotify-sys"
705version = "0.1.4" 717version = "0.1.5"
706source = "registry+https://github.com/rust-lang/crates.io-index" 718source = "registry+https://github.com/rust-lang/crates.io-index"
707checksum = "c4563555856585ab3180a5bf0b2f9f8d301a728462afffc8195b3f5394229c55" 719checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
708dependencies = [ 720dependencies = [
709 "libc", 721 "libc",
710] 722]
@@ -752,6 +764,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
752checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 764checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
753 765
754[[package]] 766[[package]]
767name = "jemalloc-ctl"
768version = "0.3.3"
769source = "registry+https://github.com/rust-lang/crates.io-index"
770checksum = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7"
771dependencies = [
772 "jemalloc-sys",
773 "libc",
774 "paste",
775]
776
777[[package]]
778name = "jemalloc-sys"
779version = "0.3.2"
780source = "registry+https://github.com/rust-lang/crates.io-index"
781checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
782dependencies = [
783 "cc",
784 "fs_extra",
785 "libc",
786]
787
788[[package]]
789name = "jemallocator"
790version = "0.3.2"
791source = "registry+https://github.com/rust-lang/crates.io-index"
792checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69"
793dependencies = [
794 "jemalloc-sys",
795 "libc",
796]
797
798[[package]]
755name = "jod-thread" 799name = "jod-thread"
756version = "0.1.2" 800version = "0.1.2"
757source = "registry+https://github.com/rust-lang/crates.io-index" 801source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -769,13 +813,7 @@ dependencies = [
769 813
770[[package]] 814[[package]]
771name = "la-arena" 815name = "la-arena"
772version = "0.1.1" 816version = "0.2.0"
773
774[[package]]
775name = "la-arena"
776version = "0.1.1"
777source = "registry+https://github.com/rust-lang/crates.io-index"
778checksum = "383ed2a74426d1051751f6483a7160b98f36068224857cd4c953b34719476fc3"
779 817
780[[package]] 818[[package]]
781name = "lazy_static" 819name = "lazy_static"
@@ -791,15 +829,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
791 829
792[[package]] 830[[package]]
793name = "libc" 831name = "libc"
794version = "0.2.81" 832version = "0.2.82"
795source = "registry+https://github.com/rust-lang/crates.io-index" 833source = "registry+https://github.com/rust-lang/crates.io-index"
796checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" 834checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
797 835
798[[package]] 836[[package]]
799name = "libloading" 837name = "libloading"
800version = "0.6.6" 838version = "0.6.7"
801source = "registry+https://github.com/rust-lang/crates.io-index" 839source = "registry+https://github.com/rust-lang/crates.io-index"
802checksum = "e9367bdfa836b7e3cf895867f7a570283444da90562980ec2263d6e1569b16bc" 840checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
803dependencies = [ 841dependencies = [
804 "cfg-if 1.0.0", 842 "cfg-if 1.0.0",
805 "winapi 0.3.9", 843 "winapi 0.3.9",
@@ -825,9 +863,9 @@ dependencies = [
825 863
826[[package]] 864[[package]]
827name = "log" 865name = "log"
828version = "0.4.11" 866version = "0.4.13"
829source = "registry+https://github.com/rust-lang/crates.io-index" 867source = "registry+https://github.com/rust-lang/crates.io-index"
830checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" 868checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
831dependencies = [ 869dependencies = [
832 "cfg-if 0.1.10", 870 "cfg-if 0.1.10",
833] 871]
@@ -1105,6 +1143,25 @@ dependencies = [
1105] 1143]
1106 1144
1107[[package]] 1145[[package]]
1146name = "paste"
1147version = "0.1.18"
1148source = "registry+https://github.com/rust-lang/crates.io-index"
1149checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
1150dependencies = [
1151 "paste-impl",
1152 "proc-macro-hack",
1153]
1154
1155[[package]]
1156name = "paste-impl"
1157version = "0.1.18"
1158source = "registry+https://github.com/rust-lang/crates.io-index"
1159checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
1160dependencies = [
1161 "proc-macro-hack",
1162]
1163
1164[[package]]
1108name = "paths" 1165name = "paths"
1109version = "0.0.0" 1166version = "0.0.0"
1110 1167
@@ -1160,9 +1217,15 @@ checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1"
1160 1217
1161[[package]] 1218[[package]]
1162name = "pin-project-lite" 1219name = "pin-project-lite"
1163version = "0.2.0" 1220version = "0.2.4"
1164source = "registry+https://github.com/rust-lang/crates.io-index" 1221source = "registry+https://github.com/rust-lang/crates.io-index"
1165checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" 1222checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
1223
1224[[package]]
1225name = "proc-macro-hack"
1226version = "0.5.19"
1227source = "registry+https://github.com/rust-lang/crates.io-index"
1228checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
1166 1229
1167[[package]] 1230[[package]]
1168name = "proc-macro2" 1231name = "proc-macro2"
@@ -1212,7 +1275,8 @@ name = "profile"
1212version = "0.0.0" 1275version = "0.0.0"
1213dependencies = [ 1276dependencies = [
1214 "cfg-if 1.0.0", 1277 "cfg-if 1.0.0",
1215 "la-arena 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1278 "jemalloc-ctl",
1279 "la-arena",
1216 "libc", 1280 "libc",
1217 "once_cell", 1281 "once_cell",
1218 "perf-event", 1282 "perf-event",
@@ -1227,10 +1291,11 @@ dependencies = [
1227 "cargo_metadata", 1291 "cargo_metadata",
1228 "cfg", 1292 "cfg",
1229 "itertools 0.10.0", 1293 "itertools 0.10.0",
1230 "la-arena 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1294 "la-arena",
1231 "log", 1295 "log",
1232 "paths", 1296 "paths",
1233 "proc_macro_api", 1297 "proc_macro_api",
1298 "profile",
1234 "rustc-hash", 1299 "rustc-hash",
1235 "serde", 1300 "serde",
1236 "serde_json", 1301 "serde_json",
@@ -1300,9 +1365,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
1300 1365
1301[[package]] 1366[[package]]
1302name = "regex" 1367name = "regex"
1303version = "1.4.2" 1368version = "1.4.3"
1304source = "registry+https://github.com/rust-lang/crates.io-index" 1369source = "registry+https://github.com/rust-lang/crates.io-index"
1305checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" 1370checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
1306dependencies = [ 1371dependencies = [
1307 "regex-syntax", 1372 "regex-syntax",
1308] 1373]
@@ -1319,16 +1384,17 @@ dependencies = [
1319 1384
1320[[package]] 1385[[package]]
1321name = "regex-syntax" 1386name = "regex-syntax"
1322version = "0.6.21" 1387version = "0.6.22"
1323source = "registry+https://github.com/rust-lang/crates.io-index" 1388source = "registry+https://github.com/rust-lang/crates.io-index"
1324checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" 1389checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
1325 1390
1326[[package]] 1391[[package]]
1327name = "rowan" 1392name = "rowan"
1328version = "0.10.1" 1393version = "0.10.5"
1329source = "registry+https://github.com/rust-lang/crates.io-index" 1394source = "registry+https://github.com/rust-lang/crates.io-index"
1330checksum = "ca9516377b32367ade2fbe1846c75afa4827c8976f1c7d05d5473573d18a1a04" 1395checksum = "e1898adeafc7d3c69913b33ee1acbbb39c726a9dbe05ff77c08b52957643e8db"
1331dependencies = [ 1396dependencies = [
1397 "hashbrown 0.10.0",
1332 "rustc-hash", 1398 "rustc-hash",
1333 "smol_str", 1399 "smol_str",
1334 "text-size", 1400 "text-size",
@@ -1352,6 +1418,7 @@ dependencies = [
1352 "ide", 1418 "ide",
1353 "ide_db", 1419 "ide_db",
1354 "itertools 0.10.0", 1420 "itertools 0.10.0",
1421 "jemallocator",
1355 "jod-thread", 1422 "jod-thread",
1356 "log", 1423 "log",
1357 "lsp-server", 1424 "lsp-server",
@@ -1483,18 +1550,18 @@ dependencies = [
1483 1550
1484[[package]] 1551[[package]]
1485name = "serde" 1552name = "serde"
1486version = "1.0.118" 1553version = "1.0.119"
1487source = "registry+https://github.com/rust-lang/crates.io-index" 1554source = "registry+https://github.com/rust-lang/crates.io-index"
1488checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" 1555checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3"
1489dependencies = [ 1556dependencies = [
1490 "serde_derive", 1557 "serde_derive",
1491] 1558]
1492 1559
1493[[package]] 1560[[package]]
1494name = "serde_derive" 1561name = "serde_derive"
1495version = "1.0.118" 1562version = "1.0.119"
1496source = "registry+https://github.com/rust-lang/crates.io-index" 1563source = "registry+https://github.com/rust-lang/crates.io-index"
1497checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" 1564checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd"
1498dependencies = [ 1565dependencies = [
1499 "proc-macro2", 1566 "proc-macro2",
1500 "quote", 1567 "quote",
@@ -1550,9 +1617,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1550 1617
1551[[package]] 1618[[package]]
1552name = "smallvec" 1619name = "smallvec"
1553version = "1.6.0" 1620version = "1.6.1"
1554source = "registry+https://github.com/rust-lang/crates.io-index" 1621source = "registry+https://github.com/rust-lang/crates.io-index"
1555checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" 1622checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
1556 1623
1557[[package]] 1624[[package]]
1558name = "smol_str" 1625name = "smol_str"
@@ -1592,9 +1659,9 @@ dependencies = [
1592 1659
1593[[package]] 1660[[package]]
1594name = "syn" 1661name = "syn"
1595version = "1.0.57" 1662version = "1.0.58"
1596source = "registry+https://github.com/rust-lang/crates.io-index" 1663source = "registry+https://github.com/rust-lang/crates.io-index"
1597checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" 1664checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
1598dependencies = [ 1665dependencies = [
1599 "proc-macro2", 1666 "proc-macro2",
1600 "quote", 1667 "quote",
@@ -1671,9 +1738,9 @@ dependencies = [
1671 1738
1672[[package]] 1739[[package]]
1673name = "thread_local" 1740name = "thread_local"
1674version = "1.0.1" 1741version = "1.1.0"
1675source = "registry+https://github.com/rust-lang/crates.io-index" 1742source = "registry+https://github.com/rust-lang/crates.io-index"
1676checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 1743checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
1677dependencies = [ 1744dependencies = [
1678 "lazy_static", 1745 "lazy_static",
1679] 1746]
@@ -1837,9 +1904,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1837 1904
1838[[package]] 1905[[package]]
1839name = "ungrammar" 1906name = "ungrammar"
1840version = "1.8.0" 1907version = "1.9.3"
1841source = "registry+https://github.com/rust-lang/crates.io-index" 1908source = "registry+https://github.com/rust-lang/crates.io-index"
1842checksum = "e33a2183403af89252547c4219a06a6cc8aef6302fee67e10e8431866af3ee72" 1909checksum = "f5901372c0f3a6a1a9d880aef134c8eaf5e54409343637508c0a344270b42d7b"
1843 1910
1844[[package]] 1911[[package]]
1845name = "unicase" 1912name = "unicase"
diff --git a/crates/assists/src/handlers/introduce_named_lifetime.rs b/crates/assists/src/handlers/introduce_named_lifetime.rs
index 3f5f44d69..02782eb6d 100644
--- a/crates/assists/src/handlers/introduce_named_lifetime.rs
+++ b/crates/assists/src/handlers/introduce_named_lifetime.rs
@@ -61,7 +61,7 @@ fn generate_fn_def_assist(
61 // compute the location which implicitly has the same lifetime as the anonymous lifetime 61 // compute the location which implicitly has the same lifetime as the anonymous lifetime
62 let loc_needing_lifetime = if let Some(self_param) = self_param { 62 let loc_needing_lifetime = if let Some(self_param) = self_param {
63 // if we have a self reference, use that 63 // if we have a self reference, use that
64 Some(self_param.self_token()?.text_range().start()) 64 Some(self_param.name()?.syntax().text_range().start())
65 } else { 65 } else {
66 // otherwise, if there's a single reference parameter without a named liftime, use that 66 // otherwise, if there's a single reference parameter without a named liftime, use that
67 let fn_params_without_lifetime: Vec<_> = param_list 67 let fn_params_without_lifetime: Vec<_> = param_list
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs
index c1af348dc..47e146128 100644
--- a/crates/completion/src/completions/keyword.rs
+++ b/crates/completion/src/completions/keyword.rs
@@ -99,7 +99,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
99 add_keyword(ctx, acc, "else if", "else if $0 {}"); 99 add_keyword(ctx, acc, "else if", "else if $0 {}");
100 } 100 }
101 if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent { 101 if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
102 add_keyword(ctx, acc, "mod", "mod $0 {}"); 102 add_keyword(ctx, acc, "mod", "mod $0");
103 } 103 }
104 if ctx.bind_pat_parent || ctx.ref_pat_parent { 104 if ctx.bind_pat_parent || ctx.ref_pat_parent {
105 add_keyword(ctx, acc, "mut", "mut "); 105 add_keyword(ctx, acc, "mut", "mut ");
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 378bd2c70..4147853e7 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -401,7 +401,9 @@ impl Builder {
401 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { 401 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
402 self.detail = detail.map(Into::into); 402 self.detail = detail.map(Into::into);
403 if let Some(detail) = &self.detail { 403 if let Some(detail) = &self.detail {
404 assert_never!(detail.contains('\n'), "multiline detail: {}", detail); 404 if assert_never!(detail.contains('\n'), "multiline detail: {}", detail) {
405 self.detail = Some(detail.splitn(2, '\n').next().unwrap().to_string());
406 }
405 } 407 }
406 self 408 self
407 } 409 }
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml
index 5d21283f7..535221294 100644
--- a/crates/hir_def/Cargo.toml
+++ b/crates/hir_def/Cargo.toml
@@ -20,7 +20,7 @@ fst = { version = "0.4", default-features = false }
20itertools = "0.10.0" 20itertools = "0.10.0"
21indexmap = "1.4.0" 21indexmap = "1.4.0"
22smallvec = "1.4.0" 22smallvec = "1.4.0"
23la-arena = "0.1.0" 23la-arena = { version = "0.2.0", path = "../../lib/arena" }
24 24
25stdx = { path = "../stdx", version = "0.0.0" } 25stdx = { path = "../stdx", version = "0.0.0" }
26base_db = { path = "../base_db", version = "0.0.0" } 26base_db = { path = "../base_db", version = "0.0.0" }
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 237c3d3f9..06f0b9b18 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -8,7 +8,7 @@ use hir_expand::{
8 name::{AsName, Name}, 8 name::{AsName, Name},
9 InFile, 9 InFile,
10}; 10};
11use la_arena::{map::ArenaMap, Arena}; 11use la_arena::{Arena, ArenaMap};
12use syntax::ast::{self, NameOwner, VisibilityOwner}; 12use syntax::ast::{self, NameOwner, VisibilityOwner};
13use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}; 13use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
14 14
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 5a86823c2..1b09ff816 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -7,7 +7,7 @@ use cfg::{CfgExpr, CfgOptions};
7use either::Either; 7use either::Either;
8use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; 8use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
9use itertools::Itertools; 9use itertools::Itertools;
10use la_arena::map::ArenaMap; 10use la_arena::ArenaMap;
11use mbe::ast_to_token_tree; 11use mbe::ast_to_token_tree;
12use syntax::{ 12use syntax::{
13 ast::{self, AstNode, AttrsOwner}, 13 ast::{self, AstNode, AttrsOwner},
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 43ee57277..344f0b6c0 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -16,7 +16,7 @@ use hir_expand::{
16 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, ExpandResult, 16 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, ExpandResult,
17 HirFileId, InFile, MacroDefId, 17 HirFileId, InFile, MacroDefId,
18}; 18};
19use la_arena::{map::ArenaMap, Arena}; 19use la_arena::{Arena, ArenaMap};
20use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
21use syntax::{ast, AstNode, AstPtr}; 21use syntax::{ast, AstNode, AstPtr};
22use test_utils::mark; 22use test_utils::mark;
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 0506a7274..6ef9fe790 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use hir_expand::{db::AstDatabase, HirFileId}; 5use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::map::ArenaMap; 6use la_arena::ArenaMap;
7use syntax::SmolStr; 7use syntax::SmolStr;
8 8
9use crate::{ 9use crate::{
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index a293df9f1..5be838f4a 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -13,7 +13,7 @@
13//! See also a neighboring `body` module. 13//! See also a neighboring `body` module.
14 14
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use la_arena::{Idx, RawId}; 16use la_arena::{Idx, RawIdx};
17use syntax::ast::RangeOp; 17use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
@@ -24,7 +24,7 @@ use crate::{
24 24
25pub type ExprId = Idx<Expr>; 25pub type ExprId = Idx<Expr>;
26pub(crate) fn dummy_expr_id() -> ExprId { 26pub(crate) fn dummy_expr_id() -> ExprId {
27 ExprId::from_raw(RawId::from(!0)) 27 ExprId::from_raw(RawIdx::from(!0))
28} 28}
29 29
30pub type PatId = Idx<Pat>; 30pub type PatId = Idx<Pat>;
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 75eab791a..3ace3be1f 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -10,7 +10,7 @@ use hir_expand::{
10 name::{name, AsName, Name}, 10 name::{name, AsName, Name},
11 InFile, 11 InFile,
12}; 12};
13use la_arena::{map::ArenaMap, Arena}; 13use la_arena::{Arena, ArenaMap};
14use syntax::ast::{self, GenericParamsOwner, NameOwner, TypeBoundsOwner}; 14use syntax::ast::{self, GenericParamsOwner, NameOwner, TypeBoundsOwner};
15 15
16use crate::{ 16use crate::{
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 91e42aa0d..ff62928df 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -20,7 +20,7 @@ use hir_expand::{
20 name::{name, AsName, Name}, 20 name::{name, AsName, Name},
21 HirFileId, InFile, 21 HirFileId, InFile,
22}; 22};
23use la_arena::{Arena, Idx, RawId}; 23use la_arena::{Arena, Idx, RawIdx};
24use rustc_hash::FxHashMap; 24use rustc_hash::FxHashMap;
25use smallvec::SmallVec; 25use smallvec::SmallVec;
26use syntax::{ast, match_ast}; 26use syntax::{ast, match_ast};
@@ -145,7 +145,6 @@ impl ItemTree {
145 macro_calls, 145 macro_calls,
146 macro_rules, 146 macro_rules,
147 macro_defs, 147 macro_defs,
148 exprs,
149 vis, 148 vis,
150 generics, 149 generics,
151 } = &mut **data; 150 } = &mut **data;
@@ -167,7 +166,6 @@ impl ItemTree {
167 macro_calls.shrink_to_fit(); 166 macro_calls.shrink_to_fit();
168 macro_rules.shrink_to_fit(); 167 macro_rules.shrink_to_fit();
169 macro_defs.shrink_to_fit(); 168 macro_defs.shrink_to_fit();
170 exprs.shrink_to_fit();
171 169
172 vis.arena.shrink_to_fit(); 170 vis.arena.shrink_to_fit();
173 generics.arena.shrink_to_fit(); 171 generics.arena.shrink_to_fit();
@@ -296,7 +294,6 @@ struct ItemTreeData {
296 macro_calls: Arena<MacroCall>, 294 macro_calls: Arena<MacroCall>,
297 macro_rules: Arena<MacroRules>, 295 macro_rules: Arena<MacroRules>,
298 macro_defs: Arena<MacroDef>, 296 macro_defs: Arena<MacroDef>,
299 exprs: Arena<Expr>,
300 297
301 vis: ItemVisibilities, 298 vis: ItemVisibilities,
302 generics: GenericParamsStorage, 299 generics: GenericParamsStorage,
@@ -461,7 +458,7 @@ macro_rules! impl_index {
461 }; 458 };
462} 459}
463 460
464impl_index!(fields: Field, variants: Variant, exprs: Expr); 461impl_index!(fields: Field, variants: Variant);
465 462
466impl Index<RawVisibilityId> for ItemTree { 463impl Index<RawVisibilityId> for ItemTree {
467 type Output = RawVisibility; 464 type Output = RawVisibility;
@@ -664,11 +661,6 @@ pub struct MacroDef {
664 pub ast_id: FileAstId<ast::MacroDef>, 661 pub ast_id: FileAstId<ast::MacroDef>,
665} 662}
666 663
667// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
668// lengths, but we don't do much with them yet.
669#[derive(Debug, Clone, Eq, PartialEq)]
670pub struct Expr;
671
672macro_rules! impl_froms { 664macro_rules! impl_froms {
673 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => { 665 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
674 $( 666 $(
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3b206ef85..5e71ca42c 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -683,12 +683,12 @@ impl Ctx {
683 } 683 }
684 684
685 fn next_field_idx(&self) -> Idx<Field> { 685 fn next_field_idx(&self) -> Idx<Field> {
686 Idx::from_raw(RawId::from( 686 Idx::from_raw(RawIdx::from(
687 self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32), 687 self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
688 )) 688 ))
689 } 689 }
690 fn next_variant_idx(&self) -> Idx<Variant> { 690 fn next_variant_idx(&self) -> Idx<Variant> {
691 Idx::from_raw(RawId::from( 691 Idx::from_raw(RawIdx::from(
692 self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), 692 self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
693 )) 693 ))
694 } 694 }
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 3dd7c3cbb..e34cd7f2f 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -87,7 +87,7 @@ impl ModPath {
87 87
88 /// If this path is a single identifier, like `foo`, return its name. 88 /// If this path is a single identifier, like `foo`, return its name.
89 pub fn as_ident(&self) -> Option<&Name> { 89 pub fn as_ident(&self) -> Option<&Name> {
90 if self.kind != PathKind::Plain || self.segments.len() > 1 { 90 if !self.is_ident() {
91 return None; 91 return None;
92 } 92 }
93 self.segments.first() 93 self.segments.first()
diff --git a/crates/hir_def/src/src.rs b/crates/hir_def/src/src.rs
index eb29265d9..751d4c052 100644
--- a/crates/hir_def/src/src.rs
+++ b/crates/hir_def/src/src.rs
@@ -1,7 +1,7 @@
1//! Utilities for mapping between hir IDs and the surface syntax. 1//! Utilities for mapping between hir IDs and the surface syntax.
2 2
3use hir_expand::InFile; 3use hir_expand::InFile;
4use la_arena::map::ArenaMap; 4use la_arena::ArenaMap;
5 5
6use crate::{db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc}; 6use crate::{db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc};
7 7
diff --git a/crates/hir_def/src/trace.rs b/crates/hir_def/src/trace.rs
index 0a9beae8e..6e6ceb8e4 100644
--- a/crates/hir_def/src/trace.rs
+++ b/crates/hir_def/src/trace.rs
@@ -9,7 +9,7 @@
9//! absolute offsets. The `Trace` structure (inspired, at least in name, by 9//! absolute offsets. The `Trace` structure (inspired, at least in name, by
10//! Kotlin's `BindingTrace`) allows use the same code to compute both 10//! Kotlin's `BindingTrace`) allows use the same code to compute both
11//! projections. 11//! projections.
12use la_arena::{map::ArenaMap, Arena, Idx, RawId}; 12use la_arena::{Arena, ArenaMap, Idx, RawIdx};
13 13
14pub(crate) struct Trace<T, V> { 14pub(crate) struct Trace<T, V> {
15 arena: Option<Arena<T>>, 15 arena: Option<Arena<T>>,
@@ -30,7 +30,7 @@ impl<T, V> Trace<T, V> {
30 let id = if let Some(arena) = &mut self.arena { 30 let id = if let Some(arena) = &mut self.arena {
31 arena.alloc(data()) 31 arena.alloc(data())
32 } else { 32 } else {
33 let id = Idx::<T>::from_raw(RawId::from(self.len)); 33 let id = Idx::<T>::from_raw(RawIdx::from(self.len));
34 self.len += 1; 34 self.len += 1;
35 id 35 id
36 }; 36 };
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs
index ae93d0d10..049b2e462 100644
--- a/crates/hir_def/src/type_ref.rs
+++ b/crates/hir_def/src/type_ref.rs
@@ -159,6 +159,8 @@ impl TypeRef {
159 ast::Type::DynTraitType(inner) => { 159 ast::Type::DynTraitType(inner) => {
160 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) 160 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
161 } 161 }
162 // FIXME: Macros in type position are not yet supported.
163 ast::Type::MacroType(_) => TypeRef::Error,
162 } 164 }
163 } 165 }
164 166
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml
index b535a3d4f..5271110d2 100644
--- a/crates/hir_expand/Cargo.toml
+++ b/crates/hir_expand/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13log = "0.4.8" 13log = "0.4.8"
14either = "1.5.3" 14either = "1.5.3"
15rustc-hash = "1.0.0" 15rustc-hash = "1.0.0"
16la-arena = "0.1.0" 16la-arena = { version = "0.2.0", path = "../../lib/arena" }
17 17
18base_db = { path = "../base_db", version = "0.0.0" } 18base_db = { path = "../base_db", version = "0.0.0" }
19syntax = { path = "../syntax", version = "0.0.0" } 19syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/crates/hir_expand/src/ast_id_map.rs b/crates/hir_expand/src/ast_id_map.rs
index f4f6e11fd..2401b0cc5 100644
--- a/crates/hir_expand/src/ast_id_map.rs
+++ b/crates/hir_expand/src/ast_id_map.rs
@@ -72,10 +72,12 @@ impl AstIdMap {
72 // get lower ids then children. That is, adding a new child does not 72 // get lower ids then children. That is, adding a new child does not
73 // change parent's id. This means that, say, adding a new function to a 73 // change parent's id. This means that, say, adding a new function to a
74 // trait does not change ids of top-level items, which helps caching. 74 // trait does not change ids of top-level items, which helps caching.
75 bfs(node, |it| { 75 bdfs(node, |it| match ast::Item::cast(it) {
76 if let Some(module_item) = ast::Item::cast(it) { 76 Some(module_item) => {
77 res.alloc(module_item.syntax()); 77 res.alloc(module_item.syntax());
78 true
78 } 79 }
80 None => false,
79 }); 81 });
80 res 82 res
81 } 83 }
@@ -105,14 +107,30 @@ impl AstIdMap {
105 } 107 }
106} 108}
107 109
108/// Walks the subtree in bfs order, calling `f` for each node. 110/// Walks the subtree in bdfs order, calling `f` for each node. What is bdfs
109fn bfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode)) { 111/// order? It is a mix of breadth-first and depth first orders. Nodes for which
112/// `f` returns true are visited breadth-first, all the other nodes are explored
113/// depth-first.
114///
115/// In other words, the size of the bfs queue is bound by the number of "true"
116/// nodes.
117fn bdfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode) -> bool) {
110 let mut curr_layer = vec![node.clone()]; 118 let mut curr_layer = vec![node.clone()];
111 let mut next_layer = vec![]; 119 let mut next_layer = vec![];
112 while !curr_layer.is_empty() { 120 while !curr_layer.is_empty() {
113 curr_layer.drain(..).for_each(|node| { 121 curr_layer.drain(..).for_each(|node| {
114 next_layer.extend(node.children()); 122 let mut preorder = node.preorder();
115 f(node); 123 while let Some(event) = preorder.next() {
124 match event {
125 syntax::WalkEvent::Enter(node) => {
126 if f(node.clone()) {
127 next_layer.extend(node.children());
128 preorder.skip_subtree();
129 }
130 }
131 syntax::WalkEvent::Leave(_) => {}
132 }
133 }
116 }); 134 });
117 std::mem::swap(&mut curr_layer, &mut next_layer); 135 std::mem::swap(&mut curr_layer, &mut next_layer);
118 } 136 }
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 8db581b77..c8ea81210 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -76,6 +76,8 @@ pub struct HygieneFrame {
76 76
77impl HygieneFrames { 77impl HygieneFrames {
78 fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Self { 78 fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Self {
79 // Note that this intentionally avoids the `hygiene_frame` query to avoid blowing up memory
80 // usage. The query is only helpful for nested `HygieneFrame`s as it avoids redundant work.
79 HygieneFrames(Arc::new(HygieneFrame::new(db, file_id))) 81 HygieneFrames(Arc::new(HygieneFrame::new(db, file_id)))
80 } 82 }
81 83
diff --git a/crates/hir_expand/src/proc_macro.rs b/crates/hir_expand/src/proc_macro.rs
index 1923daca5..75e950816 100644
--- a/crates/hir_expand/src/proc_macro.rs
+++ b/crates/hir_expand/src/proc_macro.rs
@@ -135,7 +135,6 @@ mod tests {
135 let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap()); 135 let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap());
136 136
137 assert_eq_text!( 137 assert_eq_text!(
138 &result,
139 r#" 138 r#"
140SUBTREE $ 139SUBTREE $
141 PUNCH # [alone] 0 140 PUNCH # [alone] 0
@@ -150,7 +149,8 @@ SUBTREE $
150 PUNCH : [alone] 19 149 PUNCH : [alone] 19
151 IDENT u32 20 150 IDENT u32 20
152"# 151"#
153 .trim() 152 .trim(),
153 &result
154 ); 154 );
155 } 155 }
156} 156}
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 436c1405b..98434b741 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -20,7 +20,7 @@ scoped-tls = "1"
20chalk-solve = { version = "0.47", default-features = false } 20chalk-solve = { version = "0.47", default-features = false }
21chalk-ir = "0.47" 21chalk-ir = "0.47"
22chalk-recursive = "0.47" 22chalk-recursive = "0.47"
23la-arena = "0.1.0" 23la-arena = { version = "0.2.0", path = "../../lib/arena" }
24 24
25stdx = { path = "../stdx", version = "0.0.0" } 25stdx = { path = "../stdx", version = "0.0.0" }
26hir_def = { path = "../hir_def", version = "0.0.0" } 26hir_def = { path = "../hir_def", version = "0.0.0" }
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index b0e2a3b7d..b3af82444 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -7,7 +7,7 @@ use hir_def::{
7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, 7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
8 LocalFieldId, TypeParamId, VariantId, 8 LocalFieldId, TypeParamId, VariantId,
9}; 9};
10use la_arena::map::ArenaMap; 10use la_arena::ArenaMap;
11 11
12use crate::{ 12use crate::{
13 method_resolution::{InherentImpls, TraitImpls}, 13 method_resolution::{InherentImpls, TraitImpls},
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 46a806b9a..d08867c70 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -30,7 +30,7 @@ use hir_def::{
30 TypeAliasId, VariantId, 30 TypeAliasId, VariantId,
31}; 31};
32use hir_expand::{diagnostics::DiagnosticSink, name::name}; 32use hir_expand::{diagnostics::DiagnosticSink, name::name};
33use la_arena::map::ArenaMap; 33use la_arena::ArenaMap;
34use rustc_hash::FxHashMap; 34use rustc_hash::FxHashMap;
35use stdx::impl_from; 35use stdx::impl_from;
36use syntax::SmolStr; 36use syntax::SmolStr;
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 68d16f89a..7a734c8b9 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -20,7 +20,7 @@ use hir_def::{
20 TypeAliasId, TypeParamId, UnionId, VariantId, 20 TypeAliasId, TypeParamId, UnionId, VariantId,
21}; 21};
22use hir_expand::name::Name; 22use hir_expand::name::Name;
23use la_arena::map::ArenaMap; 23use la_arena::ArenaMap;
24use smallvec::SmallVec; 24use smallvec::SmallVec;
25use stdx::impl_from; 25use stdx::impl_from;
26use test_utils::mark; 26use test_utils::mark;
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 3b1675f0b..5ff755321 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -26,7 +26,7 @@ use once_cell::race::OnceBool;
26use stdx::format_to; 26use stdx::format_to;
27use syntax::{ 27use syntax::{
28 algo, 28 algo,
29 ast::{self, AstNode}, 29 ast::{self, AstNode, NameOwner},
30 SyntaxNode, 30 SyntaxNode,
31}; 31};
32use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; 32use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
@@ -153,7 +153,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
153 }); 153 });
154 for (node, ty) in &types { 154 for (node, ty) in &types {
155 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) { 155 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) {
156 (self_param.self_token().unwrap().text_range(), "self".to_string()) 156 (self_param.name().unwrap().syntax().text_range(), "self".to_string())
157 } else { 157 } else {
158 (node.value.text_range(), node.value.text().to_string().replace("\n", " ")) 158 (node.value.text_range(), node.value.text().to_string().replace("\n", " "))
159 }; 159 };
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index e4335119b..579d5a308 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -140,7 +140,7 @@ impl DiagnosticWithFix for IncorrectCase {
140 rename_with_semantics(sema, file_position, &self.suggested_text).ok()?; 140 rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;
141 141
142 let label = format!("Rename to {}", self.suggested_text); 142 let label = format!("Rename to {}", self.suggested_text);
143 Some(Fix::new(&label, rename_changes.info, rename_changes.range)) 143 Some(Fix::new(&label, rename_changes, frange.range))
144 } 144 }
145} 145}
146 146
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 685052e7f..00e601244 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -400,15 +400,13 @@ impl TryToNav for hir::GenericParam {
400impl ToNav for hir::Local { 400impl ToNav for hir::Local {
401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 401 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
402 let src = self.source(db); 402 let src = self.source(db);
403 let (node, focus_range) = match &src.value { 403 let (node, name) = match &src.value {
404 Either::Left(bind_pat) => ( 404 Either::Left(bind_pat) => (bind_pat.syntax().clone(), bind_pat.name()),
405 bind_pat.syntax().clone(), 405 Either::Right(it) => (it.syntax().clone(), it.name()),
406 bind_pat
407 .name()
408 .map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range),
409 ),
410 Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())),
411 }; 406 };
407 let focus_range =
408 name.map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range);
409
412 let full_range = src.with_value(&node).original_file_range(db); 410 let full_range = src.with_value(&node).original_file_range(db);
413 let name = match self.name(db) { 411 let name = match self.name(db) {
414 Some(it) => it.to_string().into(), 412 Some(it) => it.to_string().into(),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 988a5668f..a1d2bce1d 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -55,11 +55,6 @@ pub(crate) fn goto_definition(
55 } else { 55 } else {
56 reference_definition(&sema, Either::Left(&lt)).to_vec() 56 reference_definition(&sema, Either::Left(&lt)).to_vec()
57 }, 57 },
58 ast::SelfParam(self_param) => {
59 let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
60 let nav = def.try_to_nav(sema.db)?;
61 vec![nav]
62 },
63 _ => return None, 58 _ => return None,
64 } 59 }
65 }; 60 };
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 6022bd275..2024acd94 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -98,7 +98,6 @@ pub(crate) fn hover(
98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) 99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), 100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
101 ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)),
102 _ => None, 101 _ => None,
103 } 102 }
104 }; 103 };
@@ -3223,7 +3222,7 @@ impl Foo {
3223} 3222}
3224"#, 3223"#,
3225 expect![[r#" 3224 expect![[r#"
3226 *&self* 3225 *self*
3227 3226
3228 ```rust 3227 ```rust
3229 &Foo 3228 &Foo
@@ -3243,7 +3242,7 @@ impl Foo {
3243} 3242}
3244"#, 3243"#,
3245 expect![[r#" 3244 expect![[r#"
3246 *self: Arc<Foo>* 3245 *self*
3247 3246
3248 ```rust 3247 ```rust
3249 Arc<Foo> 3248 Arc<Foo>
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 07f52613f..3abbb14c6 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -86,18 +86,15 @@ pub use completion::{
86 InsertTextFormat, 86 InsertTextFormat,
87}; 87};
88pub use hir::{Documentation, Semantics}; 88pub use hir::{Documentation, Semantics};
89pub use ide_db::base_db::{
90 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
91 SourceRootId,
92};
93pub use ide_db::{ 89pub use ide_db::{
90 base_db::{
91 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange,
92 SourceRoot, SourceRootId,
93 },
94 call_info::CallInfo, 94 call_info::CallInfo,
95 search::{FileReference, ReferenceAccess, ReferenceKind},
96};
97pub use ide_db::{
98 label::Label, 95 label::Label,
99 line_index::{LineCol, LineIndex}, 96 line_index::{LineCol, LineIndex},
100 search::SearchScope, 97 search::{FileReference, ReferenceAccess, ReferenceKind, SearchScope},
101 source_change::{FileSystemEdit, SourceChange}, 98 source_change::{FileSystemEdit, SourceChange},
102 symbol_index::Query, 99 symbol_index::Query,
103 RootDatabase, 100 RootDatabase,
@@ -525,7 +522,7 @@ impl Analysis {
525 &self, 522 &self,
526 position: FilePosition, 523 position: FilePosition,
527 new_name: &str, 524 new_name: &str,
528 ) -> Cancelable<Result<RangeInfo<SourceChange>, RenameError>> { 525 ) -> Cancelable<Result<SourceChange, RenameError>> {
529 self.with_db(|db| references::rename::rename(db, position, new_name)) 526 self.with_db(|db| references::rename::rename(db, position, new_name))
530 } 527 }
531 528
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 51a2f4327..df9c31aef 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -930,6 +930,26 @@ impl Foo {
930 ); 930 );
931 } 931 }
932 932
933 #[test]
934 fn test_find_self_refs_decl() {
935 check(
936 r#"
937struct Foo { bar: i32 }
938
939impl Foo {
940 fn foo(self$0) {
941 self;
942 }
943}
944"#,
945 expect![[r#"
946 self SelfParam FileId(0) 47..51 47..51 SelfParam
947
948 FileId(0) 63..67 Other Read
949 "#]],
950 );
951 }
952
933 fn check(ra_fixture: &str, expect: Expect) { 953 fn check(ra_fixture: &str, expect: Expect) {
934 check_with_scope(ra_fixture, None, expect) 954 check_with_scope(ra_fixture, None, expect)
935 } 955 }
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 9ac4af026..c25bcce50 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -1,27 +1,25 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use std::{ 2use std::fmt::{self, Display};
3 convert::TryInto,
4 fmt::{self, Display},
5};
6 3
7use hir::{Module, ModuleDef, ModuleSource, Semantics}; 4use either::Either;
5use hir::{HasSource, InFile, Module, ModuleDef, ModuleSource, Semantics};
8use ide_db::{ 6use ide_db::{
9 base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}, 7 base_db::{AnchoredPathBuf, FileId, FileRange},
10 defs::{Definition, NameClass, NameRefClass}, 8 defs::{Definition, NameClass, NameRefClass},
11 search::FileReference, 9 search::FileReference,
12 RootDatabase, 10 RootDatabase,
13}; 11};
12use stdx::assert_never;
14use syntax::{ 13use syntax::{
15 algo::find_node_at_offset,
16 ast::{self, NameOwner}, 14 ast::{self, NameOwner},
17 lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T, 15 lex_single_syntax_kind, AstNode, SyntaxKind, SyntaxNode, T,
18}; 16};
19use test_utils::mark; 17use test_utils::mark;
20use text_edit::TextEdit; 18use text_edit::TextEdit;
21 19
22use crate::{ 20use crate::{
23 FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, 21 display::TryToNav, FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, SourceChange,
24 TextRange, TextSize, 22 TextRange,
25}; 23};
26 24
27type RenameResult<T> = Result<T, RenameError>; 25type RenameResult<T> = Result<T, RenameError>;
@@ -50,24 +48,22 @@ pub(crate) fn prepare_rename(
50 let sema = Semantics::new(db); 48 let sema = Semantics::new(db);
51 let source_file = sema.parse(position.file_id); 49 let source_file = sema.parse(position.file_id);
52 let syntax = source_file.syntax(); 50 let syntax = source_file.syntax();
53 if let Some(module) = find_module_at_offset(&sema, position, syntax) { 51 let range = match &find_name_like(&sema, &syntax, position)
54 rename_mod(&sema, position, module, "dummy") 52 .ok_or_else(|| format_err!("No references found at position"))?
55 } else if let Some(self_token) =
56 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
57 { 53 {
58 rename_self_to_param(&sema, position, self_token, "dummy") 54 NameLike::Name(it) => it.syntax(),
59 } else { 55 NameLike::NameRef(it) => it.syntax(),
60 let RangeInfo { range, .. } = find_all_refs(&sema, position)?; 56 NameLike::Lifetime(it) => it.syntax(),
61 Ok(RangeInfo::new(range, SourceChange::default()))
62 } 57 }
63 .map(|info| RangeInfo::new(info.range, ())) 58 .text_range();
59 Ok(RangeInfo::new(range, ()))
64} 60}
65 61
66pub(crate) fn rename( 62pub(crate) fn rename(
67 db: &RootDatabase, 63 db: &RootDatabase,
68 position: FilePosition, 64 position: FilePosition,
69 new_name: &str, 65 new_name: &str,
70) -> RenameResult<RangeInfo<SourceChange>> { 66) -> RenameResult<SourceChange> {
71 let sema = Semantics::new(db); 67 let sema = Semantics::new(db);
72 rename_with_semantics(&sema, position, new_name) 68 rename_with_semantics(&sema, position, new_name)
73} 69}
@@ -76,18 +72,15 @@ pub(crate) fn rename_with_semantics(
76 sema: &Semantics<RootDatabase>, 72 sema: &Semantics<RootDatabase>,
77 position: FilePosition, 73 position: FilePosition,
78 new_name: &str, 74 new_name: &str,
79) -> RenameResult<RangeInfo<SourceChange>> { 75) -> RenameResult<SourceChange> {
80 let source_file = sema.parse(position.file_id); 76 let source_file = sema.parse(position.file_id);
81 let syntax = source_file.syntax(); 77 let syntax = source_file.syntax();
82 78
83 if let Some(module) = find_module_at_offset(&sema, position, syntax) { 79 let def = find_definition(sema, syntax, position)
84 rename_mod(&sema, position, module, new_name) 80 .ok_or_else(|| format_err!("No references found at position"))?;
85 } else if let Some(self_token) = 81 match def {
86 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) 82 Definition::ModuleDef(ModuleDef::Module(module)) => rename_mod(&sema, module, new_name),
87 { 83 def => rename_reference(sema, def, new_name),
88 rename_self_to_param(&sema, position, self_token, new_name)
89 } else {
90 rename_reference(&sema, position, new_name)
91 } 84 }
92} 85}
93 86
@@ -98,17 +91,12 @@ pub(crate) fn will_rename_file(
98) -> Option<SourceChange> { 91) -> Option<SourceChange> {
99 let sema = Semantics::new(db); 92 let sema = Semantics::new(db);
100 let module = sema.to_module_def(file_id)?; 93 let module = sema.to_module_def(file_id)?;
101 94 let mut change = rename_mod(&sema, module, new_name_stem).ok()?;
102 let decl = module.declaration_source(db)?;
103 let range = decl.value.name()?.syntax().text_range();
104
105 let position = FilePosition { file_id: decl.file_id.original_file(db), offset: range.start() };
106 let mut change = rename_mod(&sema, position, module, new_name_stem).ok()?.info;
107 change.file_system_edits.clear(); 95 change.file_system_edits.clear();
108 Some(change) 96 Some(change)
109} 97}
110 98
111#[derive(Debug, PartialEq)] 99#[derive(Copy, Clone, Debug, PartialEq)]
112enum IdentifierKind { 100enum IdentifierKind {
113 Ident, 101 Ident,
114 Lifetime, 102 Lifetime,
@@ -135,40 +123,51 @@ fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> {
135 } 123 }
136} 124}
137 125
138fn find_module_at_offset( 126enum NameLike {
127 Name(ast::Name),
128 NameRef(ast::NameRef),
129 Lifetime(ast::Lifetime),
130}
131
132fn find_name_like(
139 sema: &Semantics<RootDatabase>, 133 sema: &Semantics<RootDatabase>,
140 position: FilePosition,
141 syntax: &SyntaxNode, 134 syntax: &SyntaxNode,
142) -> Option<Module> { 135 position: FilePosition,
143 let ident = syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::IDENT)?; 136) -> Option<NameLike> {
144 137 let namelike = if let Some(name_ref) =
145 let module = match_ast! { 138 sema.find_node_at_offset_with_descend::<ast::NameRef>(syntax, position.offset)
146 match (ident.parent()) { 139 {
147 ast::NameRef(name_ref) => { 140 NameLike::NameRef(name_ref)
148 match NameRefClass::classify(sema, &name_ref)? { 141 } else if let Some(name) =
149 NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, 142 sema.find_node_at_offset_with_descend::<ast::Name>(syntax, position.offset)
150 _ => return None, 143 {
151 } 144 NameLike::Name(name)
152 }, 145 } else if let Some(lifetime) =
153 ast::Name(name) => { 146 sema.find_node_at_offset_with_descend::<ast::Lifetime>(syntax, position.offset)
154 match NameClass::classify(&sema, &name)? { 147 {
155 NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module, 148 NameLike::Lifetime(lifetime)
156 _ => return None, 149 } else {
157 } 150 return None;
158 },
159 _ => return None,
160 }
161 }; 151 };
162 152 Some(namelike)
163 Some(module)
164} 153}
165 154
166fn find_all_refs( 155fn find_definition(
167 sema: &Semantics<RootDatabase>, 156 sema: &Semantics<RootDatabase>,
157 syntax: &SyntaxNode,
168 position: FilePosition, 158 position: FilePosition,
169) -> RenameResult<RangeInfo<ReferenceSearchResult>> { 159) -> Option<Definition> {
170 crate::references::find_all_refs(sema, position, None) 160 let def = match find_name_like(sema, syntax, position)? {
171 .ok_or_else(|| format_err!("No references found at position")) 161 NameLike::Name(name) => NameClass::classify(sema, &name)?.referenced_or_defined(sema.db),
162 NameLike::NameRef(name_ref) => NameRefClass::classify(sema, &name_ref)?.referenced(sema.db),
163 NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
164 .map(|class| NameRefClass::referenced(class, sema.db))
165 .or_else(|| {
166 NameClass::classify_lifetime(sema, &lifetime)
167 .map(|it| it.referenced_or_defined(sema.db))
168 })?,
169 };
170 Some(def)
172} 171}
173 172
174fn source_edit_from_references( 173fn source_edit_from_references(
@@ -242,72 +241,84 @@ fn edit_text_range_for_record_field_expr_or_pat(
242 241
243fn rename_mod( 242fn rename_mod(
244 sema: &Semantics<RootDatabase>, 243 sema: &Semantics<RootDatabase>,
245 position: FilePosition,
246 module: Module, 244 module: Module,
247 new_name: &str, 245 new_name: &str,
248) -> RenameResult<RangeInfo<SourceChange>> { 246) -> RenameResult<SourceChange> {
249 if IdentifierKind::Ident != check_identifier(new_name)? { 247 if IdentifierKind::Ident != check_identifier(new_name)? {
250 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); 248 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
251 } 249 }
252 250
253 let mut source_change = SourceChange::default(); 251 let mut source_change = SourceChange::default();
254 252
255 let src = module.definition_source(sema.db); 253 let InFile { file_id, value: def_source } = module.definition_source(sema.db);
256 let file_id = src.file_id.original_file(sema.db); 254 let file_id = file_id.original_file(sema.db);
257 match src.value { 255 if let ModuleSource::SourceFile(..) = def_source {
258 ModuleSource::SourceFile(..) => { 256 // mod is defined in path/to/dir/mod.rs
259 // mod is defined in path/to/dir/mod.rs 257 let path = if module.is_mod_rs(sema.db) {
260 let path = if module.is_mod_rs(sema.db) { 258 format!("../{}/mod.rs", new_name)
261 format!("../{}/mod.rs", new_name) 259 } else {
262 } else { 260 format!("{}.rs", new_name)
263 format!("{}.rs", new_name) 261 };
264 }; 262 let dst = AnchoredPathBuf { anchor: file_id, path };
265 let dst = AnchoredPathBuf { anchor: file_id, path }; 263 let move_file = FileSystemEdit::MoveFile { src: file_id, dst };
266 let move_file = FileSystemEdit::MoveFile { src: file_id, dst }; 264 source_change.push_file_system_edit(move_file);
267 source_change.push_file_system_edit(move_file); 265 }
268 } 266
269 ModuleSource::Module(..) => {} 267 if let Some(InFile { file_id, value: decl_source }) = module.declaration_source(sema.db) {
270 } 268 let file_id = file_id.original_file(sema.db);
271 269 match decl_source.name() {
272 if let Some(src) = module.declaration_source(sema.db) { 270 Some(name) => source_change.insert_source_edit(
273 let file_id = src.file_id.original_file(sema.db); 271 file_id,
274 let name = src.value.name().unwrap(); 272 TextEdit::replace(name.syntax().text_range(), new_name.to_string()),
275 source_change.insert_source_edit( 273 ),
276 file_id, 274 _ => unreachable!(),
277 TextEdit::replace(name.syntax().text_range(), new_name.into()), 275 };
278 );
279 } 276 }
280 277 let def = Definition::ModuleDef(ModuleDef::Module(module));
281 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; 278 let usages = def.usages(sema).all();
282 let ref_edits = refs.references().iter().map(|(&file_id, references)| { 279 let ref_edits = usages.iter().map(|(&file_id, references)| {
283 source_edit_from_references(sema, file_id, references, new_name) 280 source_edit_from_references(sema, file_id, references, new_name)
284 }); 281 });
285 source_change.extend(ref_edits); 282 source_change.extend(ref_edits);
286 283
287 Ok(RangeInfo::new(range, source_change)) 284 Ok(source_change)
288} 285}
289 286
290fn rename_to_self( 287fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> {
291 sema: &Semantics<RootDatabase>, 288 if assert_never!(local.is_self(sema.db)) {
292 position: FilePosition, 289 bail!("rename_to_self invoked on self");
293) -> Result<RangeInfo<SourceChange>, RenameError> { 290 }
294 let source_file = sema.parse(position.file_id); 291
295 let syn = source_file.syntax(); 292 let fn_def = match local.parent(sema.db) {
293 hir::DefWithBody::Function(func) => func,
294 _ => bail!("Cannot rename non-param local to self"),
295 };
296
297 // FIXME: reimplement this on the hir instead
298 // as of the time of this writing params in hir don't keep their names
299 let fn_ast =
300 fn_def.source(sema.db).ok_or(format_err!("Cannot rename non-param local to self"))?.value;
296 301
297 let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) 302 let first_param_range = fn_ast
298 .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast)))
299 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
300 let param_range = fn_ast
301 .param_list() 303 .param_list()
302 .and_then(|p| p.params().next()) 304 .and_then(|p| p.params().next())
303 .ok_or_else(|| format_err!("Method has no parameters"))? 305 .ok_or_else(|| format_err!("Method has no parameters"))?
304 .syntax() 306 .syntax()
305 .text_range(); 307 .text_range();
306 if !param_range.contains(position.offset) { 308 let InFile { file_id, value: local_source } = local.source(sema.db);
307 bail!("Only the first parameter can be self"); 309 match local_source {
310 either::Either::Left(pat)
311 if !first_param_range.contains_range(pat.syntax().text_range()) =>
312 {
313 bail!("Only the first parameter can be self");
314 }
315 _ => (),
308 } 316 }
309 317
310 let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) 318 let impl_block = fn_ast
319 .syntax()
320 .ancestors()
321 .find_map(|node| ast::Impl::cast(node))
311 .and_then(|def| sema.to_def(&def)) 322 .and_then(|def| sema.to_def(&def))
312 .ok_or_else(|| format_err!("No impl block found for function"))?; 323 .ok_or_else(|| format_err!("No impl block found for function"))?;
313 if fn_def.self_param(sema.db).is_some() { 324 if fn_def.self_param(sema.db).is_some() {
@@ -331,25 +342,21 @@ fn rename_to_self(
331 bail!("Parameter type differs from impl block type"); 342 bail!("Parameter type differs from impl block type");
332 } 343 }
333 344
334 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; 345 let def = Definition::Local(local);
335 346 let usages = def.usages(sema).all();
336 let mut source_change = SourceChange::default(); 347 let mut source_change = SourceChange::default();
337 source_change.extend(refs.references().iter().map(|(&file_id, references)| { 348 source_change.extend(usages.iter().map(|(&file_id, references)| {
338 source_edit_from_references(sema, file_id, references, "self") 349 source_edit_from_references(sema, file_id, references, "self")
339 })); 350 }));
340 source_change.insert_source_edit( 351 source_change.insert_source_edit(
341 position.file_id, 352 file_id.original_file(sema.db),
342 TextEdit::replace(param_range, String::from(self_param)), 353 TextEdit::replace(first_param_range, String::from(self_param)),
343 ); 354 );
344 355
345 Ok(RangeInfo::new(range, source_change)) 356 Ok(source_change)
346} 357}
347 358
348fn text_edit_from_self_param( 359fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Option<TextEdit> {
349 syn: &SyntaxNode,
350 self_param: &ast::SelfParam,
351 new_name: &str,
352) -> Option<TextEdit> {
353 fn target_type_name(impl_def: &ast::Impl) -> Option<String> { 360 fn target_type_name(impl_def: &ast::Impl) -> Option<String> {
354 if let Some(ast::Type::PathType(p)) = impl_def.self_ty() { 361 if let Some(ast::Type::PathType(p)) = impl_def.self_ty() {
355 return Some(p.path()?.segment()?.name_ref()?.text().to_string()); 362 return Some(p.path()?.segment()?.name_ref()?.text().to_string());
@@ -357,7 +364,7 @@ fn text_edit_from_self_param(
357 None 364 None
358 } 365 }
359 366
360 let impl_def = find_node_at_offset::<ast::Impl>(syn, self_param.syntax().text_range().start())?; 367 let impl_def = self_param.syntax().ancestors().find_map(|it| ast::Impl::cast(it))?;
361 let type_name = target_type_name(&impl_def)?; 368 let type_name = target_type_name(&impl_def)?;
362 369
363 let mut replacement_text = String::from(new_name); 370 let mut replacement_text = String::from(new_name);
@@ -374,96 +381,119 @@ fn text_edit_from_self_param(
374 381
375fn rename_self_to_param( 382fn rename_self_to_param(
376 sema: &Semantics<RootDatabase>, 383 sema: &Semantics<RootDatabase>,
377 position: FilePosition, 384 local: hir::Local,
378 self_token: SyntaxToken,
379 new_name: &str, 385 new_name: &str,
380) -> Result<RangeInfo<SourceChange>, RenameError> { 386 identifier_kind: IdentifierKind,
381 let ident_kind = check_identifier(new_name)?; 387) -> RenameResult<SourceChange> {
382 match ident_kind { 388 let (file_id, self_param) = match local.source(sema.db) {
383 IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), 389 InFile { file_id, value: Either::Right(self_param) } => (file_id, self_param),
384 IdentifierKind::ToSelf => { 390 _ => {
385 // no-op 391 assert_never!(true, "rename_self_to_param invoked on a non-self local");
386 mark::hit!(rename_self_to_self); 392 bail!("rename_self_to_param invoked on a non-self local");
387 return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default()));
388 }
389 _ => (),
390 }
391 let source_file = sema.parse(position.file_id);
392 let syn = source_file.syntax();
393
394 let text = sema.db.file_text(position.file_id);
395 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
396 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
397 let search_range = fn_def.syntax().text_range();
398
399 let mut source_change = SourceChange::default();
400
401 for (idx, _) in text.match_indices("self") {
402 let offset: TextSize = idx.try_into().unwrap();
403 if !search_range.contains_inclusive(offset) {
404 continue;
405 } 393 }
406 if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) { 394 };
407 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
408 text_edit_from_self_param(syn, self_param, new_name)
409 .ok_or_else(|| format_err!("No target type found"))?
410 } else {
411 TextEdit::replace(usage.text_range(), String::from(new_name))
412 };
413 source_change.insert_source_edit(position.file_id, edit);
414 }
415 }
416 395
417 if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore { 396 let def = Definition::Local(local);
397 let usages = def.usages(sema).all();
398 let edit = text_edit_from_self_param(&self_param, new_name)
399 .ok_or_else(|| format_err!("No target type found"))?;
400 if usages.len() > 1 && identifier_kind == IdentifierKind::Underscore {
418 bail!("Cannot rename reference to `_` as it is being referenced multiple times"); 401 bail!("Cannot rename reference to `_` as it is being referenced multiple times");
419 } 402 }
420 403 let mut source_change = SourceChange::default();
421 let range = ast::SelfParam::cast(self_token.parent()) 404 source_change.insert_source_edit(file_id.original_file(sema.db), edit);
422 .map_or(self_token.text_range(), |p| p.syntax().text_range()); 405 source_change.extend(usages.iter().map(|(&file_id, references)| {
423 406 source_edit_from_references(sema, file_id, &references, new_name)
424 Ok(RangeInfo::new(range, source_change)) 407 }));
408 Ok(source_change)
425} 409}
426 410
427fn rename_reference( 411fn rename_reference(
428 sema: &Semantics<RootDatabase>, 412 sema: &Semantics<RootDatabase>,
429 position: FilePosition, 413 def: Definition,
430 new_name: &str, 414 new_name: &str,
431) -> Result<RangeInfo<SourceChange>, RenameError> { 415) -> RenameResult<SourceChange> {
432 let ident_kind = check_identifier(new_name)?; 416 let ident_kind = check_identifier(new_name)?;
433 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
434 417
435 match (ident_kind, &refs.declaration.kind) { 418 let def_is_lbl_or_lt = matches!(def,
436 (IdentifierKind::ToSelf, ReferenceKind::Lifetime) 419 Definition::GenericParam(hir::GenericParam::LifetimeParam(_))
437 | (IdentifierKind::Underscore, ReferenceKind::Lifetime) 420 | Definition::Label(_)
438 | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { 421 );
422 match (ident_kind, def) {
423 (IdentifierKind::ToSelf, _)
424 | (IdentifierKind::Underscore, _)
425 | (IdentifierKind::Ident, _)
426 if def_is_lbl_or_lt =>
427 {
439 mark::hit!(rename_not_a_lifetime_ident_ref); 428 mark::hit!(rename_not_a_lifetime_ident_ref);
440 bail!("Invalid name `{}`: not a lifetime identifier", new_name) 429 bail!("Invalid name `{}`: not a lifetime identifier", new_name)
441 } 430 }
442 (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => mark::hit!(rename_lifetime), 431 (IdentifierKind::Lifetime, _) if def_is_lbl_or_lt => mark::hit!(rename_lifetime),
443 (IdentifierKind::Lifetime, _) => { 432 (IdentifierKind::Lifetime, _) => {
444 mark::hit!(rename_not_an_ident_ref); 433 mark::hit!(rename_not_an_ident_ref);
445 bail!("Invalid name `{}`: not an identifier", new_name) 434 bail!("Invalid name `{}`: not an identifier", new_name)
446 } 435 }
447 (IdentifierKind::ToSelf, ReferenceKind::SelfParam) => { 436 (IdentifierKind::ToSelf, Definition::Local(local)) if local.is_self(sema.db) => {
448 unreachable!("rename_self_to_param should've been called instead") 437 // no-op
438 mark::hit!(rename_self_to_self);
439 return Ok(SourceChange::default());
449 } 440 }
450 (IdentifierKind::ToSelf, _) => { 441 (ident_kind, Definition::Local(local)) if local.is_self(sema.db) => {
451 mark::hit!(rename_to_self); 442 mark::hit!(rename_self_to_param);
452 return rename_to_self(sema, position); 443 return rename_self_to_param(sema, local, new_name, ident_kind);
453 } 444 }
454 (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { 445 (IdentifierKind::ToSelf, Definition::Local(local)) => {
455 mark::hit!(rename_underscore_multiple); 446 mark::hit!(rename_to_self);
456 bail!("Cannot rename reference to `_` as it is being referenced multiple times") 447 return rename_to_self(sema, local);
457 } 448 }
449 (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name),
458 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), 450 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident),
459 } 451 }
460 452
453 let usages = def.usages(sema).all();
454 if !usages.is_empty() && ident_kind == IdentifierKind::Underscore {
455 mark::hit!(rename_underscore_multiple);
456 bail!("Cannot rename reference to `_` as it is being referenced multiple times");
457 }
461 let mut source_change = SourceChange::default(); 458 let mut source_change = SourceChange::default();
462 source_change.extend(refs.into_iter().map(|(file_id, references)| { 459 source_change.extend(usages.iter().map(|(&file_id, references)| {
463 source_edit_from_references(sema, file_id, &references, new_name) 460 source_edit_from_references(sema, file_id, &references, new_name)
464 })); 461 }));
465 462
466 Ok(RangeInfo::new(range, source_change)) 463 let (file_id, edit) = source_edit_from_def(sema, def, new_name)?;
464 source_change.insert_source_edit(file_id, edit);
465 Ok(source_change)
466}
467
468fn source_edit_from_def(
469 sema: &Semantics<RootDatabase>,
470 def: Definition,
471 new_name: &str,
472) -> RenameResult<(FileId, TextEdit)> {
473 let nav = def.try_to_nav(sema.db).unwrap();
474
475 let mut replacement_text = String::new();
476 let mut repl_range = nav.focus_or_full_range();
477 if let Definition::Local(local) = def {
478 if let Either::Left(pat) = local.source(sema.db).value {
479 if matches!(
480 pat.syntax().parent().and_then(ast::RecordPatField::cast),
481 Some(pat_field) if pat_field.name_ref().is_none()
482 ) {
483 replacement_text.push_str(": ");
484 replacement_text.push_str(new_name);
485 repl_range = TextRange::new(
486 pat.syntax().text_range().end(),
487 pat.syntax().text_range().end(),
488 );
489 }
490 }
491 }
492 if replacement_text.is_empty() {
493 replacement_text.push_str(new_name);
494 }
495 let edit = TextEdit::replace(repl_range, replacement_text);
496 Ok((nav.file_id, edit))
467} 497}
468 498
469#[cfg(test)] 499#[cfg(test)]
@@ -485,7 +515,7 @@ mod tests {
485 Ok(source_change) => { 515 Ok(source_change) => {
486 let mut text_edit_builder = TextEdit::builder(); 516 let mut text_edit_builder = TextEdit::builder();
487 let mut file_id: Option<FileId> = None; 517 let mut file_id: Option<FileId> = None;
488 for edit in source_change.info.source_file_edits { 518 for edit in source_change.source_file_edits {
489 file_id = Some(edit.0); 519 file_id = Some(edit.0);
490 for indel in edit.1.into_iter() { 520 for indel in edit.1.into_iter() {
491 text_edit_builder.replace(indel.delete, indel.insert); 521 text_edit_builder.replace(indel.delete, indel.insert);
@@ -884,36 +914,33 @@ mod foo$0;
884// empty 914// empty
885"#, 915"#,
886 expect![[r#" 916 expect![[r#"
887 RangeInfo { 917 SourceChange {
888 range: 4..7, 918 source_file_edits: {
889 info: SourceChange { 919 FileId(
890 source_file_edits: { 920 1,
891 FileId( 921 ): TextEdit {
892 1, 922 indels: [
893 ): TextEdit { 923 Indel {
894 indels: [ 924 insert: "foo2",
895 Indel { 925 delete: 4..7,
896 insert: "foo2", 926 },
897 delete: 4..7, 927 ],
898 },
899 ],
900 },
901 }, 928 },
902 file_system_edits: [ 929 },
903 MoveFile { 930 file_system_edits: [
904 src: FileId( 931 MoveFile {
932 src: FileId(
933 2,
934 ),
935 dst: AnchoredPathBuf {
936 anchor: FileId(
905 2, 937 2,
906 ), 938 ),
907 dst: AnchoredPathBuf { 939 path: "foo2.rs",
908 anchor: FileId(
909 2,
910 ),
911 path: "foo2.rs",
912 },
913 }, 940 },
914 ], 941 },
915 is_snippet: false, 942 ],
916 }, 943 is_snippet: false,
917 } 944 }
918 "#]], 945 "#]],
919 ); 946 );
@@ -936,46 +963,43 @@ pub struct FooContent;
936use crate::foo$0::FooContent; 963use crate::foo$0::FooContent;
937"#, 964"#,
938 expect![[r#" 965 expect![[r#"
939 RangeInfo { 966 SourceChange {
940 range: 11..14, 967 source_file_edits: {
941 info: SourceChange { 968 FileId(
942 source_file_edits: { 969 0,
943 FileId( 970 ): TextEdit {
944 0, 971 indels: [
945 ): TextEdit { 972 Indel {
946 indels: [ 973 insert: "quux",
947 Indel { 974 delete: 8..11,
948 insert: "quux", 975 },
949 delete: 8..11, 976 ],
950 }, 977 },
951 ], 978 FileId(
952 }, 979 2,
953 FileId( 980 ): TextEdit {
954 2, 981 indels: [
955 ): TextEdit { 982 Indel {
956 indels: [ 983 insert: "quux",
957 Indel { 984 delete: 11..14,
958 insert: "quux", 985 },
959 delete: 11..14, 986 ],
960 },
961 ],
962 },
963 }, 987 },
964 file_system_edits: [ 988 },
965 MoveFile { 989 file_system_edits: [
966 src: FileId( 990 MoveFile {
991 src: FileId(
992 1,
993 ),
994 dst: AnchoredPathBuf {
995 anchor: FileId(
967 1, 996 1,
968 ), 997 ),
969 dst: AnchoredPathBuf { 998 path: "quux.rs",
970 anchor: FileId(
971 1,
972 ),
973 path: "quux.rs",
974 },
975 }, 999 },
976 ], 1000 },
977 is_snippet: false, 1001 ],
978 }, 1002 is_snippet: false,
979 } 1003 }
980 "#]], 1004 "#]],
981 ); 1005 );
@@ -992,36 +1016,33 @@ mod fo$0o;
992// empty 1016// empty
993"#, 1017"#,
994 expect![[r#" 1018 expect![[r#"
995 RangeInfo { 1019 SourceChange {
996 range: 4..7, 1020 source_file_edits: {
997 info: SourceChange { 1021 FileId(
998 source_file_edits: { 1022 0,
999 FileId( 1023 ): TextEdit {
1000 0, 1024 indels: [
1001 ): TextEdit { 1025 Indel {
1002 indels: [ 1026 insert: "foo2",
1003 Indel { 1027 delete: 4..7,
1004 insert: "foo2", 1028 },
1005 delete: 4..7, 1029 ],
1006 },
1007 ],
1008 },
1009 }, 1030 },
1010 file_system_edits: [ 1031 },
1011 MoveFile { 1032 file_system_edits: [
1012 src: FileId( 1033 MoveFile {
1034 src: FileId(
1035 1,
1036 ),
1037 dst: AnchoredPathBuf {
1038 anchor: FileId(
1013 1, 1039 1,
1014 ), 1040 ),
1015 dst: AnchoredPathBuf { 1041 path: "../foo2/mod.rs",
1016 anchor: FileId(
1017 1,
1018 ),
1019 path: "../foo2/mod.rs",
1020 },
1021 }, 1042 },
1022 ], 1043 },
1023 is_snippet: false, 1044 ],
1024 }, 1045 is_snippet: false,
1025 } 1046 }
1026 "#]], 1047 "#]],
1027 ); 1048 );
@@ -1039,36 +1060,33 @@ mod outer { mod fo$0o; }
1039// empty 1060// empty
1040"#, 1061"#,
1041 expect![[r#" 1062 expect![[r#"
1042 RangeInfo { 1063 SourceChange {
1043 range: 16..19, 1064 source_file_edits: {
1044 info: SourceChange { 1065 FileId(
1045 source_file_edits: { 1066 0,
1046 FileId( 1067 ): TextEdit {
1047 0, 1068 indels: [
1048 ): TextEdit { 1069 Indel {
1049 indels: [ 1070 insert: "bar",
1050 Indel { 1071 delete: 16..19,
1051 insert: "bar", 1072 },
1052 delete: 16..19, 1073 ],
1053 },
1054 ],
1055 },
1056 }, 1074 },
1057 file_system_edits: [ 1075 },
1058 MoveFile { 1076 file_system_edits: [
1059 src: FileId( 1077 MoveFile {
1078 src: FileId(
1079 1,
1080 ),
1081 dst: AnchoredPathBuf {
1082 anchor: FileId(
1060 1, 1083 1,
1061 ), 1084 ),
1062 dst: AnchoredPathBuf { 1085 path: "bar.rs",
1063 anchor: FileId(
1064 1,
1065 ),
1066 path: "bar.rs",
1067 },
1068 }, 1086 },
1069 ], 1087 },
1070 is_snippet: false, 1088 ],
1071 }, 1089 is_snippet: false,
1072 } 1090 }
1073 "#]], 1091 "#]],
1074 ); 1092 );
@@ -1109,46 +1127,43 @@ pub mod foo$0;
1109// pub fn fun() {} 1127// pub fn fun() {}
1110"#, 1128"#,
1111 expect![[r#" 1129 expect![[r#"
1112 RangeInfo { 1130 SourceChange {
1113 range: 8..11, 1131 source_file_edits: {
1114 info: SourceChange { 1132 FileId(
1115 source_file_edits: { 1133 0,
1116 FileId( 1134 ): TextEdit {
1117 0, 1135 indels: [
1118 ): TextEdit { 1136 Indel {
1119 indels: [ 1137 insert: "foo2",
1120 Indel { 1138 delete: 27..30,
1121 insert: "foo2", 1139 },
1122 delete: 27..30, 1140 ],
1123 },
1124 ],
1125 },
1126 FileId(
1127 1,
1128 ): TextEdit {
1129 indels: [
1130 Indel {
1131 insert: "foo2",
1132 delete: 8..11,
1133 },
1134 ],
1135 },
1136 }, 1141 },
1137 file_system_edits: [ 1142 FileId(
1138 MoveFile { 1143 1,
1139 src: FileId( 1144 ): TextEdit {
1145 indels: [
1146 Indel {
1147 insert: "foo2",
1148 delete: 8..11,
1149 },
1150 ],
1151 },
1152 },
1153 file_system_edits: [
1154 MoveFile {
1155 src: FileId(
1156 2,
1157 ),
1158 dst: AnchoredPathBuf {
1159 anchor: FileId(
1140 2, 1160 2,
1141 ), 1161 ),
1142 dst: AnchoredPathBuf { 1162 path: "foo2.rs",
1143 anchor: FileId(
1144 2,
1145 ),
1146 path: "foo2.rs",
1147 },
1148 }, 1163 },
1149 ], 1164 },
1150 is_snippet: false, 1165 ],
1151 }, 1166 is_snippet: false,
1152 } 1167 }
1153 "#]], 1168 "#]],
1154 ); 1169 );
@@ -1350,6 +1365,7 @@ impl Foo {
1350 1365
1351 #[test] 1366 #[test]
1352 fn test_owned_self_to_parameter() { 1367 fn test_owned_self_to_parameter() {
1368 mark::check!(rename_self_to_param);
1353 check( 1369 check(
1354 "foo", 1370 "foo",
1355 r#" 1371 r#"
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 87578e70a..8625ef5df 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -68,7 +68,8 @@ pub(super) fn element(
68 NAME_REF => { 68 NAME_REF => {
69 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 69 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
70 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { 70 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
71 match NameRefClass::classify(sema, &name_ref) { 71 let is_self = name_ref.self_token().is_some();
72 let h = match NameRefClass::classify(sema, &name_ref) {
72 Some(name_kind) => match name_kind { 73 Some(name_kind) => match name_kind {
73 NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), 74 NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(),
74 NameRefClass::Definition(def) => { 75 NameRefClass::Definition(def) => {
@@ -108,6 +109,11 @@ pub(super) fn element(
108 highlight_name_ref_by_syntax(name_ref, sema) 109 highlight_name_ref_by_syntax(name_ref, sema)
109 } 110 }
110 None => HlTag::UnresolvedReference.into(), 111 None => HlTag::UnresolvedReference.into(),
112 };
113 if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self {
114 HlTag::Symbol(SymbolKind::SelfParam).into()
115 } else {
116 h
111 } 117 }
112 }) 118 })
113 } 119 }
@@ -225,18 +231,8 @@ pub(super) fn element(
225 T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, 231 T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow,
226 T![unsafe] => h | HlMod::Unsafe, 232 T![unsafe] => h | HlMod::Unsafe,
227 T![true] | T![false] => HlTag::BoolLiteral.into(), 233 T![true] | T![false] => HlTag::BoolLiteral.into(),
228 T![self] => { 234 // self is handled as either a Name or NameRef already
229 let self_param = element.parent().and_then(ast::SelfParam::cast); 235 T![self] => return None,
230 if let Some(NameClass::Definition(def)) = self_param
231 .and_then(|self_param| NameClass::classify_self_param(sema, &self_param))
232 {
233 highlight_def(db, def) | HlMod::Definition
234 } else if element.ancestors().any(|it| it.kind() == USE_TREE) {
235 HlTag::Symbol(SymbolKind::SelfParam).into()
236 } else {
237 return None;
238 }
239 }
240 T![ref] => element 236 T![ref] => element
241 .parent() 237 .parent()
242 .and_then(ast::IdentPat::cast) 238 .and_then(ast::IdentPat::cast)
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index 1d4bac7ad..4c63d3023 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -111,7 +111,6 @@ mod tests {
111 let syn = analysis.syntax_tree(file_id, None).unwrap(); 111 let syn = analysis.syntax_tree(file_id, None).unwrap();
112 112
113 assert_eq_text!( 113 assert_eq_text!(
114 syn.trim(),
115 r#" 114 r#"
116[email protected] 115[email protected]
117 [email protected] 116 [email protected]
@@ -127,7 +126,8 @@ [email protected]
127 [email protected] "{" 126 [email protected] "{"
128 [email protected] "}" 127 [email protected] "}"
129"# 128"#
130 .trim() 129 .trim(),
130 syn.trim()
131 ); 131 );
132 132
133 let (analysis, file_id) = fixture::file( 133 let (analysis, file_id) = fixture::file(
@@ -143,7 +143,6 @@ fn test() {
143 let syn = analysis.syntax_tree(file_id, None).unwrap(); 143 let syn = analysis.syntax_tree(file_id, None).unwrap();
144 144
145 assert_eq_text!( 145 assert_eq_text!(
146 syn.trim(),
147 r#" 146 r#"
148[email protected] 147[email protected]
149 [email protected] 148 [email protected]
@@ -176,7 +175,8 @@ [email protected]
176 [email protected] "\n" 175 [email protected] "\n"
177 [email protected] "}" 176 [email protected] "}"
178"# 177"#
179 .trim() 178 .trim(),
179 syn.trim()
180 ); 180 );
181 } 181 }
182 182
@@ -186,7 +186,6 @@ [email protected]
186 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 186 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
187 187
188 assert_eq_text!( 188 assert_eq_text!(
189 syn.trim(),
190 r#" 189 r#"
191[email protected] 190[email protected]
192 [email protected] "fn" 191 [email protected] "fn"
@@ -201,7 +200,8 @@ [email protected]
201 [email protected] "{" 200 [email protected] "{"
202 [email protected] "}" 201 [email protected] "}"
203"# 202"#
204 .trim() 203 .trim(),
204 syn.trim()
205 ); 205 );
206 206
207 let (analysis, range) = fixture::range( 207 let (analysis, range) = fixture::range(
@@ -216,7 +216,6 @@ [email protected]
216 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 216 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
217 217
218 assert_eq_text!( 218 assert_eq_text!(
219 syn.trim(),
220 r#" 219 r#"
221[email protected] 220[email protected]
222 [email protected] 221 [email protected]
@@ -234,7 +233,8 @@ [email protected]
234 [email protected] ")" 233 [email protected] ")"
235 [email protected] ";" 234 [email protected] ";"
236"# 235"#
237 .trim() 236 .trim(),
237 syn.trim()
238 ); 238 );
239 } 239 }
240 240
@@ -253,7 +253,6 @@ fn bar() {
253 ); 253 );
254 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 254 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
255 assert_eq_text!( 255 assert_eq_text!(
256 syn.trim(),
257 r#" 256 r#"
258[email protected] 257[email protected]
259 [email protected] 258 [email protected]
@@ -270,7 +269,8 @@ [email protected]
270 [email protected] "\n" 269 [email protected] "\n"
271 [email protected] "}" 270 [email protected] "}"
272"# 271"#
273 .trim() 272 .trim(),
273 syn.trim()
274 ); 274 );
275 275
276 // With a raw string 276 // With a raw string
@@ -287,7 +287,6 @@ fn bar() {
287 ); 287 );
288 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 288 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
289 assert_eq_text!( 289 assert_eq_text!(
290 syn.trim(),
291 r#" 290 r#"
292[email protected] 291[email protected]
293 [email protected] 292 [email protected]
@@ -304,7 +303,8 @@ [email protected]
304 [email protected] "\n" 303 [email protected] "\n"
305 [email protected] "}" 304 [email protected] "}"
306"# 305"#
307 .trim() 306 .trim(),
307 syn.trim()
308 ); 308 );
309 309
310 // With a raw string 310 // With a raw string
@@ -320,7 +320,6 @@ fn bar() {
320 ); 320 );
321 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 321 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
322 assert_eq_text!( 322 assert_eq_text!(
323 syn.trim(),
324 r#" 323 r#"
325[email protected] 324[email protected]
326 [email protected] 325 [email protected]
@@ -351,7 +350,8 @@ [email protected]
351 [email protected] "\n" 350 [email protected] "\n"
352 [email protected] "}" 351 [email protected] "}"
353"# 352"#
354 .trim() 353 .trim(),
354 syn.trim()
355 ); 355 );
356 } 356 }
357} 357}
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 231e886a9..d9875ffef 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -117,13 +117,6 @@ impl NameClass {
117 } 117 }
118 } 118 }
119 119
120 pub fn classify_self_param(
121 sema: &Semantics<RootDatabase>,
122 self_param: &ast::SelfParam,
123 ) -> Option<NameClass> {
124 sema.to_def(self_param).map(Definition::Local).map(NameClass::Definition)
125 }
126
127 pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { 120 pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
128 let _p = profile::span("classify_name"); 121 let _p = profile::span("classify_name");
129 122
@@ -186,6 +179,10 @@ impl NameClass {
186 179
187 Some(NameClass::Definition(Definition::Local(local))) 180 Some(NameClass::Definition(Definition::Local(local)))
188 }, 181 },
182 ast::SelfParam(it) => {
183 let def = sema.to_def(&it)?;
184 Some(NameClass::Definition(Definition::Local(def.into())))
185 },
189 ast::RecordField(it) => { 186 ast::RecordField(it) => {
190 let field: hir::Field = sema.to_def(&it)?; 187 let field: hir::Field = sema.to_def(&it)?;
191 Some(NameClass::Definition(Definition::Field(field))) 188 Some(NameClass::Definition(Definition::Field(field)))
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
index a603fe87f..4bbe66f1f 100644
--- a/crates/ide_db/src/helpers/insert_use/tests.rs
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -599,7 +599,7 @@ fn check(
599 599
600 let rewriter = insert_use(&file, path, mb); 600 let rewriter = insert_use(&file, path, mb);
601 let result = rewriter.rewrite(file.as_syntax_node()).to_string(); 601 let result = rewriter.rewrite(file.as_syntax_node()).to_string();
602 assert_eq_text!(&result, ra_fixture_after); 602 assert_eq_text!(ra_fixture_after, &result);
603} 603}
604 604
605fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 605fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index e648519f9..2a41d8167 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -51,6 +51,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke
51 let global_offset = node.text_range().start(); 51 let global_offset = node.text_range().start();
52 let mut c = Convertor::new(node, global_offset); 52 let mut c = Convertor::new(node, global_offset);
53 let subtree = c.go()?; 53 let subtree = c.go()?;
54 c.id_alloc.map.entries.shrink_to_fit();
54 Some((subtree, c.id_alloc.map)) 55 Some((subtree, c.id_alloc.map))
55} 56}
56 57
@@ -593,7 +594,8 @@ impl<'a> TtTreeSink<'a> {
593 } 594 }
594 } 595 }
595 596
596 fn finish(self) -> (Parse<SyntaxNode>, TokenMap) { 597 fn finish(mut self) -> (Parse<SyntaxNode>, TokenMap) {
598 self.token_map.entries.shrink_to_fit();
597 (self.inner.finish(), self.token_map) 599 (self.inner.finish(), self.token_map)
598 } 600 }
599} 601}
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 9ff901e97..bd2977ebd 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -261,7 +261,6 @@ fn test_expr_order() {
261 261
262 let dump = format!("{:#?}", expanded); 262 let dump = format!("{:#?}", expanded);
263 assert_eq_text!( 263 assert_eq_text!(
264 dump.trim(),
265 r#"[email protected] 264 r#"[email protected]
266 [email protected] 265 [email protected]
267 [email protected] "fn" 266 [email protected] "fn"
@@ -285,6 +284,7 @@ fn test_expr_order() {
285 [email protected] "2" 284 [email protected] "2"
286 [email protected] ";" 285 [email protected] ";"
287 [email protected] "}""#, 286 [email protected] "}""#,
287 dump.trim()
288 ); 288 );
289} 289}
290 290
@@ -989,7 +989,6 @@ fn test_tt_composite2() {
989 989
990 let res = format!("{:#?}", &node); 990 let res = format!("{:#?}", &node);
991 assert_eq_text!( 991 assert_eq_text!(
992 res.trim(),
993 r###"[email protected] 992 r###"[email protected]
994 [email protected] 993 [email protected]
995 [email protected] 994 [email protected]
@@ -1003,7 +1002,8 @@ fn test_tt_composite2() {
1003 [email protected] ">" 1002 [email protected] ">"
1004 [email protected] " " 1003 [email protected] " "
1005 [email protected] "#" 1004 [email protected] "#"
1006 [email protected] ")""### 1005 [email protected] ")""###,
1006 res.trim()
1007 ); 1007 );
1008} 1008}
1009 1009
@@ -1742,7 +1742,7 @@ impl MacroFixture {
1742 fn assert_expand(&self, invocation: &str, expected: &str) { 1742 fn assert_expand(&self, invocation: &str, expected: &str) {
1743 let expansion = self.expand_tt(invocation); 1743 let expansion = self.expand_tt(invocation);
1744 let actual = format!("{:?}", expansion); 1744 let actual = format!("{:?}", expansion);
1745 test_utils::assert_eq_text!(&actual.trim(), &expected.trim()); 1745 test_utils::assert_eq_text!(&expected.trim(), &actual.trim());
1746 } 1746 }
1747 1747
1748 fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { 1748 fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture {
@@ -1941,7 +1941,6 @@ fn test_no_space_after_semi_colon() {
1941 1941
1942 let dump = format!("{:#?}", expanded); 1942 let dump = format!("{:#?}", expanded);
1943 assert_eq_text!( 1943 assert_eq_text!(
1944 dump.trim(),
1945 r###"[email protected] 1944 r###"[email protected]
1946 [email protected] 1945 [email protected]
1947 [email protected] 1946 [email protected]
@@ -1981,6 +1980,7 @@ fn test_no_space_after_semi_colon() {
1981 [email protected] 1980 [email protected]
1982 [email protected] "f" 1981 [email protected] "f"
1983 [email protected] ";""###, 1982 [email protected] ";""###,
1983 dump.trim()
1984 ); 1984 );
1985} 1985}
1986 1986
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index bb9ffea8b..6913e9ec2 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -190,17 +190,25 @@ fn opt_visibility(p: &mut Parser) -> bool {
190 // test crate_visibility 190 // test crate_visibility
191 // pub(crate) struct S; 191 // pub(crate) struct S;
192 // pub(self) struct S; 192 // pub(self) struct S;
193 // pub(self) struct S; 193 // pub(super) struct S;
194 // pub(self) struct S;
195 194
196 // test pub_parens_typepath 195 // test pub_parens_typepath
197 // struct B(pub (super::A)); 196 // struct B(pub (super::A));
198 // struct B(pub (crate::A,)); 197 // struct B(pub (crate::A,));
199 T![crate] | T![self] | T![super] if p.nth(2) != T![:] => { 198 T![crate] | T![self] | T![super] if p.nth(2) != T![:] => {
200 p.bump_any(); 199 p.bump_any();
200 let path_m = p.start();
201 let path_segment_m = p.start();
202 let name_ref_m = p.start();
201 p.bump_any(); 203 p.bump_any();
204 name_ref_m.complete(p, NAME_REF);
205 path_segment_m.complete(p, PATH_SEGMENT);
206 path_m.complete(p, PATH);
202 p.expect(T![')']); 207 p.expect(T![')']);
203 } 208 }
209 // test crate_visibility_in
210 // pub(in super::A) struct S;
211 // pub(in crate) struct S;
204 T![in] => { 212 T![in] => {
205 p.bump_any(); 213 p.bump_any();
206 p.bump_any(); 214 p.bump_any();
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 2070ce163..1d894e907 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -270,7 +270,9 @@ fn extern_crate(p: &mut Parser, m: Marker) {
270 p.bump(T![crate]); 270 p.bump(T![crate]);
271 271
272 if p.at(T![self]) { 272 if p.at(T![self]) {
273 let m = p.start();
273 p.bump(T![self]); 274 p.bump(T![self]);
275 m.complete(p, NAME_REF);
274 } else { 276 } else {
275 name_ref(p); 277 name_ref(p);
276 } 278 }
diff --git a/crates/parser/src/grammar/items/traits.rs b/crates/parser/src/grammar/items/traits.rs
index d076974ed..d3327271c 100644
--- a/crates/parser/src/grammar/items/traits.rs
+++ b/crates/parser/src/grammar/items/traits.rs
@@ -40,6 +40,10 @@ pub(super) fn impl_(p: &mut Parser) {
40 type_params::opt_generic_param_list(p); 40 type_params::opt_generic_param_list(p);
41 } 41 }
42 42
43 // test impl_def_const
44 // impl const Send for X {}
45 p.eat(T![const]);
46
43 // FIXME: never type 47 // FIXME: never type
44 // impl ! {} 48 // impl ! {}
45 49
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 2d006a1d5..6a98d7368 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -156,7 +156,7 @@ fn variadic_param(p: &mut Parser) -> bool {
156fn opt_self_param(p: &mut Parser, m: Marker) { 156fn opt_self_param(p: &mut Parser, m: Marker) {
157 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] { 157 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
158 p.eat(T![mut]); 158 p.eat(T![mut]);
159 p.eat(T![self]); 159 self_as_name(p);
160 // test arb_self_types 160 // test arb_self_types
161 // impl S { 161 // impl S {
162 // fn a(self: &Self) {} 162 // fn a(self: &Self) {}
@@ -169,24 +169,29 @@ fn opt_self_param(p: &mut Parser, m: Marker) {
169 let la1 = p.nth(1); 169 let la1 = p.nth(1);
170 let la2 = p.nth(2); 170 let la2 = p.nth(2);
171 let la3 = p.nth(3); 171 let la3 = p.nth(3);
172 let mut n_toks = match (p.current(), la1, la2, la3) { 172 if !matches!((p.current(), la1, la2, la3),
173 (T![&], T![self], _, _) => 2, 173 (T![&], T![self], _, _)
174 (T![&], T![mut], T![self], _) => 3, 174 | (T![&], T![mut], T![self], _)
175 (T![&], LIFETIME_IDENT, T![self], _) => 3, 175 | (T![&], LIFETIME_IDENT, T![self], _)
176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4, 176 | (T![&], LIFETIME_IDENT, T![mut], T![self])
177 _ => return m.abandon(p), 177 ) {
178 }; 178 return m.abandon(p);
179 p.bump_any(); 179 }
180 p.bump(T![&]);
180 if p.at(LIFETIME_IDENT) { 181 if p.at(LIFETIME_IDENT) {
181 lifetime(p); 182 lifetime(p);
182 n_toks -= 1;
183 }
184 for _ in 1..n_toks {
185 p.bump_any();
186 } 183 }
184 p.eat(T![mut]);
185 self_as_name(p);
187 } 186 }
188 m.complete(p, SELF_PARAM); 187 m.complete(p, SELF_PARAM);
189 if !p.at(T![')']) { 188 if !p.at(T![')']) {
190 p.expect(T![,]); 189 p.expect(T![,]);
191 } 190 }
192} 191}
192
193fn self_as_name(p: &mut Parser) {
194 let m = p.start();
195 p.bump(T![self]);
196 m.complete(p, NAME);
197}
diff --git a/crates/parser/src/syntax_kind.rs b/crates/parser/src/syntax_kind.rs
index 63204436c..9ea0e4f9b 100644
--- a/crates/parser/src/syntax_kind.rs
+++ b/crates/parser/src/syntax_kind.rs
@@ -6,6 +6,7 @@ mod generated;
6pub use self::generated::SyntaxKind; 6pub use self::generated::SyntaxKind;
7 7
8impl From<u16> for SyntaxKind { 8impl From<u16> for SyntaxKind {
9 #[inline]
9 fn from(d: u16) -> SyntaxKind { 10 fn from(d: u16) -> SyntaxKind {
10 assert!(d <= (SyntaxKind::__LAST as u16)); 11 assert!(d <= (SyntaxKind::__LAST as u16));
11 unsafe { std::mem::transmute::<u16, SyntaxKind>(d) } 12 unsafe { std::mem::transmute::<u16, SyntaxKind>(d) }
@@ -13,12 +14,14 @@ impl From<u16> for SyntaxKind {
13} 14}
14 15
15impl From<SyntaxKind> for u16 { 16impl From<SyntaxKind> for u16 {
17 #[inline]
16 fn from(k: SyntaxKind) -> u16 { 18 fn from(k: SyntaxKind) -> u16 {
17 k as u16 19 k as u16
18 } 20 }
19} 21}
20 22
21impl SyntaxKind { 23impl SyntaxKind {
24 #[inline]
22 pub fn is_trivia(self) -> bool { 25 pub fn is_trivia(self) -> bool {
23 matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) 26 matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT)
24 } 27 }
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 7d53cc4cd..bcefd183a 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -143,6 +143,7 @@ pub enum SyntaxKind {
143 MACRO_DEF, 143 MACRO_DEF,
144 PAREN_TYPE, 144 PAREN_TYPE,
145 TUPLE_TYPE, 145 TUPLE_TYPE,
146 MACRO_TYPE,
146 NEVER_TYPE, 147 NEVER_TYPE,
147 PATH_TYPE, 148 PATH_TYPE,
148 PTR_TYPE, 149 PTR_TYPE,
diff --git a/crates/proc_macro_api/Cargo.toml b/crates/proc_macro_api/Cargo.toml
index 1af2bbca7..078568cb2 100644
--- a/crates/proc_macro_api/Cargo.toml
+++ b/crates/proc_macro_api/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11 11
12[dependencies] 12[dependencies]
13serde = { version = "1.0", features = ["derive"] } 13serde = { version = "1.0", features = ["derive"] }
14serde_json = "1.0" 14serde_json = { version = "1.0", features = ["unbounded_depth"] }
15log = "0.4.8" 15log = "0.4.8"
16crossbeam-channel = "0.5.0" 16crossbeam-channel = "0.5.0"
17jod-thread = "0.1.1" 17jod-thread = "0.1.1"
diff --git a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
index e6fd21610..ea34e688f 100644
--- a/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
+++ b/crates/proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
@@ -59,7 +59,7 @@ SUBTREE $
59 IDENT _serde 4294967295 59 IDENT _serde 4294967295
60 PUNCH : [joint] 4294967295 60 PUNCH : [joint] 4294967295
61 PUNCH : [alone] 4294967295 61 PUNCH : [alone] 4294967295
62 IDENT export 4294967295 62 IDENT __private 4294967295
63 PUNCH : [joint] 4294967295 63 PUNCH : [joint] 4294967295
64 PUNCH : [alone] 4294967295 64 PUNCH : [alone] 4294967295
65 IDENT Ok 4294967295 65 IDENT Ok 4294967295
@@ -72,7 +72,7 @@ SUBTREE $
72 IDENT _serde 4294967295 72 IDENT _serde 4294967295
73 PUNCH : [joint] 4294967295 73 PUNCH : [joint] 4294967295
74 PUNCH : [alone] 4294967295 74 PUNCH : [alone] 4294967295
75 IDENT export 4294967295 75 IDENT __private 4294967295
76 PUNCH : [joint] 4294967295 76 PUNCH : [joint] 4294967295
77 PUNCH : [alone] 4294967295 77 PUNCH : [alone] 4294967295
78 IDENT Err 4294967295 78 IDENT Err 4294967295
@@ -85,7 +85,7 @@ SUBTREE $
85 IDENT _serde 4294967295 85 IDENT _serde 4294967295
86 PUNCH : [joint] 4294967295 86 PUNCH : [joint] 4294967295
87 PUNCH : [alone] 4294967295 87 PUNCH : [alone] 4294967295
88 IDENT export 4294967295 88 IDENT __private 4294967295
89 PUNCH : [joint] 4294967295 89 PUNCH : [joint] 4294967295
90 PUNCH : [alone] 4294967295 90 PUNCH : [alone] 4294967295
91 IDENT Err 4294967295 91 IDENT Err 4294967295
@@ -120,7 +120,7 @@ SUBTREE $
120 IDENT _serde 4294967295 120 IDENT _serde 4294967295
121 PUNCH : [joint] 4294967295 121 PUNCH : [joint] 4294967295
122 PUNCH : [alone] 4294967295 122 PUNCH : [alone] 4294967295
123 IDENT export 4294967295 123 IDENT __private 4294967295
124 PUNCH : [joint] 4294967295 124 PUNCH : [joint] 4294967295
125 PUNCH : [alone] 4294967295 125 PUNCH : [alone] 4294967295
126 IDENT Result 4294967295 126 IDENT Result 4294967295
diff --git a/crates/proc_macro_srv/src/tests/mod.rs b/crates/proc_macro_srv/src/tests/mod.rs
index 1a827cbd7..fd54f8dfd 100644
--- a/crates/proc_macro_srv/src/tests/mod.rs
+++ b/crates/proc_macro_srv/src/tests/mod.rs
@@ -38,9 +38,9 @@ fn test_derive_proc_macro_list() {
38 let res = list("serde_derive", "1").join("\n"); 38 let res = list("serde_derive", "1").join("\n");
39 39
40 assert_eq_text!( 40 assert_eq_text!(
41 &res,
42 r#"Serialize [CustomDerive] 41 r#"Serialize [CustomDerive]
43Deserialize [CustomDerive]"# 42Deserialize [CustomDerive]"#,
43 &res
44 ); 44 );
45} 45}
46 46
@@ -50,9 +50,9 @@ fn list_test_macros() {
50 let res = list("proc_macro_test", "0.0.0").join("\n"); 50 let res = list("proc_macro_test", "0.0.0").join("\n");
51 51
52 assert_eq_text!( 52 assert_eq_text!(
53 &res,
54 r#"function_like_macro [FuncLike] 53 r#"function_like_macro [FuncLike]
55attribute_macro [Attr] 54attribute_macro [Attr]
56DummyTrait [CustomDerive]"# 55DummyTrait [CustomDerive]"#,
56 &res
57 ); 57 );
58} 58}
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs
index 36942147d..196abb8fc 100644
--- a/crates/proc_macro_srv/src/tests/utils.rs
+++ b/crates/proc_macro_srv/src/tests/utils.rs
@@ -52,7 +52,7 @@ pub fn assert_expand(
52 let fixture = parse_string(ra_fixture).unwrap(); 52 let fixture = parse_string(ra_fixture).unwrap();
53 53
54 let res = expander.expand(macro_name, &fixture.subtree, None).unwrap(); 54 let res = expander.expand(macro_name, &fixture.subtree, None).unwrap();
55 assert_eq_text!(&format!("{:?}", res), &expect.trim()); 55 assert_eq_text!(&expect.trim(), &format!("{:?}", res));
56} 56}
57 57
58pub fn list(crate_name: &str, version: &str) -> Vec<String> { 58pub fn list(crate_name: &str, version: &str) -> Vec<String> {
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml
index 096233a09..f7231c2b8 100644
--- a/crates/profile/Cargo.toml
+++ b/crates/profile/Cargo.toml
@@ -13,13 +13,15 @@ doctest = false
13once_cell = "1.3.1" 13once_cell = "1.3.1"
14cfg-if = "1" 14cfg-if = "1"
15libc = "0.2.73" 15libc = "0.2.73"
16la-arena = "0.1.0" 16la-arena = { version = "0.2.0", path = "../../lib/arena" }
17jemalloc-ctl = { version = "0.3.3", optional = true }
17 18
18[target.'cfg(target_os = "linux")'.dependencies] 19[target.'cfg(target_os = "linux")'.dependencies]
19perf-event = "0.4" 20perf-event = "0.4"
20 21
21[features] 22[features]
22cpu_profiler = [] 23cpu_profiler = []
24jemalloc = ["jemalloc-ctl"]
23 25
24# Uncomment to enable for the whole crate graph 26# Uncomment to enable for the whole crate graph
25# default = [ "cpu_profiler" ] 27# default = [ "cpu_profiler" ]
diff --git a/crates/profile/src/memory_usage.rs b/crates/profile/src/memory_usage.rs
index 83390212a..cb4e54447 100644
--- a/crates/profile/src/memory_usage.rs
+++ b/crates/profile/src/memory_usage.rs
@@ -24,7 +24,12 @@ impl std::ops::Sub for MemoryUsage {
24impl MemoryUsage { 24impl MemoryUsage {
25 pub fn current() -> MemoryUsage { 25 pub fn current() -> MemoryUsage {
26 cfg_if! { 26 cfg_if! {
27 if #[cfg(all(target_os = "linux", target_env = "gnu"))] { 27 if #[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] {
28 jemalloc_ctl::epoch::advance().unwrap();
29 MemoryUsage {
30 allocated: Bytes(jemalloc_ctl::stats::allocated::read().unwrap() as isize),
31 }
32 } else if #[cfg(all(target_os = "linux", target_env = "gnu"))] {
28 // Note: This is incredibly slow. 33 // Note: This is incredibly slow.
29 let alloc = unsafe { libc::mallinfo() }.uordblks as isize; 34 let alloc = unsafe { libc::mallinfo() }.uordblks as isize;
30 MemoryUsage { allocated: Bytes(alloc) } 35 MemoryUsage { allocated: Bytes(alloc) }
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml
index 51e7a7070..293cb5bfe 100644
--- a/crates/project_model/Cargo.toml
+++ b/crates/project_model/Cargo.toml
@@ -17,7 +17,7 @@ serde = { version = "1.0.106", features = ["derive"] }
17serde_json = "1.0.48" 17serde_json = "1.0.48"
18anyhow = "1.0.26" 18anyhow = "1.0.26"
19itertools = "0.10.0" 19itertools = "0.10.0"
20la-arena = "0.1.0" 20la-arena = { version = "0.2.0", path = "../../lib/arena" }
21 21
22cfg = { path = "../cfg", version = "0.0.0" } 22cfg = { path = "../cfg", version = "0.0.0" }
23base_db = { path = "../base_db", version = "0.0.0" } 23base_db = { path = "../base_db", version = "0.0.0" }
@@ -25,3 +25,4 @@ toolchain = { path = "../toolchain", version = "0.0.0" }
25proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } 25proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
26paths = { path = "../paths", version = "0.0.0" } 26paths = { path = "../paths", version = "0.0.0" }
27stdx = { path = "../stdx", version = "0.0.0" } 27stdx = { path = "../stdx", version = "0.0.0" }
28profile = { path = "../profile", version = "0.0.0" }
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs
index aabb7a47d..970a7e140 100644
--- a/crates/project_model/src/lib.rs
+++ b/crates/project_model/src/lib.rs
@@ -5,6 +5,7 @@ mod cfg_flag;
5mod project_json; 5mod project_json;
6mod sysroot; 6mod sysroot;
7mod workspace; 7mod workspace;
8mod rustc_cfg;
8 9
9use std::{ 10use std::{
10 fs::{read_dir, ReadDir}, 11 fs::{read_dir, ReadDir},
diff --git a/crates/project_model/src/rustc_cfg.rs b/crates/project_model/src/rustc_cfg.rs
new file mode 100644
index 000000000..4a7bd8ae3
--- /dev/null
+++ b/crates/project_model/src/rustc_cfg.rs
@@ -0,0 +1,34 @@
1//! Runs `rustc --print cfg` to get built-in cfg flags.
2
3use std::process::Command;
4
5use crate::{cfg_flag::CfgFlag, utf8_stdout};
6
7pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> {
8 let _p = profile::span("rustc_cfg::get");
9 let mut res = Vec::new();
10
11 // Some nightly-only cfgs, which are required for stdlib
12 res.push(CfgFlag::Atom("target_thread_local".into()));
13 for &ty in ["8", "16", "32", "64", "cas", "ptr"].iter() {
14 for &key in ["target_has_atomic", "target_has_atomic_load_store"].iter() {
15 res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() });
16 }
17 }
18
19 let rustc_cfgs = {
20 let mut cmd = Command::new(toolchain::rustc());
21 cmd.args(&["--print", "cfg", "-O"]);
22 if let Some(target) = target {
23 cmd.args(&["--target", target]);
24 }
25 utf8_stdout(cmd)
26 };
27
28 match rustc_cfgs {
29 Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())),
30 Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
31 }
32
33 res
34}
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 06a0be284..8e0481ae9 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -16,7 +16,7 @@ use proc_macro_api::ProcMacroClient;
16use rustc_hash::{FxHashMap, FxHashSet}; 16use rustc_hash::{FxHashMap, FxHashSet};
17 17
18use crate::{ 18use crate::{
19 cargo_workspace, cfg_flag::CfgFlag, sysroot::SysrootCrate, utf8_stdout, CargoConfig, 19 cargo_workspace, cfg_flag::CfgFlag, rustc_cfg, sysroot::SysrootCrate, utf8_stdout, CargoConfig,
20 CargoWorkspace, ProjectJson, ProjectManifest, Sysroot, TargetKind, 20 CargoWorkspace, ProjectJson, ProjectManifest, Sysroot, TargetKind,
21}; 21};
22 22
@@ -34,15 +34,25 @@ pub struct PackageRoot {
34#[derive(Clone, Eq, PartialEq)] 34#[derive(Clone, Eq, PartialEq)]
35pub enum ProjectWorkspace { 35pub enum ProjectWorkspace {
36 /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. 36 /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
37 Cargo { cargo: CargoWorkspace, sysroot: Sysroot, rustc: Option<CargoWorkspace> }, 37 Cargo {
38 cargo: CargoWorkspace,
39 sysroot: Sysroot,
40 rustc: Option<CargoWorkspace>,
41 /// Holds cfg flags for the current target. We get those by running
42 /// `rustc --print cfg`.
43 ///
44 /// FIXME: make this a per-crate map, as, eg, build.rs might have a
45 /// different target.
46 rustc_cfg: Vec<CfgFlag>,
47 },
38 /// Project workspace was manually specified using a `rust-project.json` file. 48 /// Project workspace was manually specified using a `rust-project.json` file.
39 Json { project: ProjectJson, sysroot: Option<Sysroot> }, 49 Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> },
40} 50}
41 51
42impl fmt::Debug for ProjectWorkspace { 52impl fmt::Debug for ProjectWorkspace {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self { 54 match self {
45 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => f 55 ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f
46 .debug_struct("Cargo") 56 .debug_struct("Cargo")
47 .field("n_packages", &cargo.packages().len()) 57 .field("n_packages", &cargo.packages().len())
48 .field("n_sysroot_crates", &sysroot.crates().len()) 58 .field("n_sysroot_crates", &sysroot.crates().len())
@@ -50,13 +60,15 @@ impl fmt::Debug for ProjectWorkspace {
50 "n_rustc_compiler_crates", 60 "n_rustc_compiler_crates",
51 &rustc.as_ref().map_or(0, |rc| rc.packages().len()), 61 &rustc.as_ref().map_or(0, |rc| rc.packages().len()),
52 ) 62 )
63 .field("rustc_cfg", rustc_cfg)
53 .finish(), 64 .finish(),
54 ProjectWorkspace::Json { project, sysroot } => { 65 ProjectWorkspace::Json { project, sysroot, rustc_cfg } => {
55 let mut debug_struct = f.debug_struct("Json"); 66 let mut debug_struct = f.debug_struct("Json");
56 debug_struct.field("n_crates", &project.n_crates()); 67 debug_struct.field("n_crates", &project.n_crates());
57 if let Some(sysroot) = sysroot { 68 if let Some(sysroot) = sysroot {
58 debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); 69 debug_struct.field("n_sysroot_crates", &sysroot.crates().len());
59 } 70 }
71 debug_struct.field("rustc_cfg", rustc_cfg);
60 debug_struct.finish() 72 debug_struct.finish()
61 } 73 }
62 } 74 }
@@ -79,7 +91,7 @@ impl ProjectWorkspace {
79 })?; 91 })?;
80 let project_location = project_json.parent().unwrap().to_path_buf(); 92 let project_location = project_json.parent().unwrap().to_path_buf();
81 let project_json = ProjectJson::new(&project_location, data); 93 let project_json = ProjectJson::new(&project_location, data);
82 ProjectWorkspace::load_inline(project_json)? 94 ProjectWorkspace::load_inline(project_json, config.target.as_deref())?
83 } 95 }
84 ProjectManifest::CargoToml(cargo_toml) => { 96 ProjectManifest::CargoToml(cargo_toml) => {
85 let cargo_version = utf8_stdout({ 97 let cargo_version = utf8_stdout({
@@ -117,21 +129,24 @@ impl ProjectWorkspace {
117 } else { 129 } else {
118 None 130 None
119 }; 131 };
120 132 let rustc_cfg = rustc_cfg::get(config.target.as_deref());
121 ProjectWorkspace::Cargo { cargo, sysroot, rustc } 133 ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg }
122 } 134 }
123 }; 135 };
124 136
125 Ok(res) 137 Ok(res)
126 } 138 }
127 139
128 pub fn load_inline(project_json: ProjectJson) -> Result<ProjectWorkspace> { 140 pub fn load_inline(
141 project_json: ProjectJson,
142 target: Option<&str>,
143 ) -> Result<ProjectWorkspace> {
129 let sysroot = match &project_json.sysroot_src { 144 let sysroot = match &project_json.sysroot_src {
130 Some(path) => Some(Sysroot::load(path)?), 145 Some(path) => Some(Sysroot::load(path)?),
131 None => None, 146 None => None,
132 }; 147 };
133 148 let rustc_cfg = rustc_cfg::get(target);
134 Ok(ProjectWorkspace::Json { project: project_json, sysroot }) 149 Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
135 } 150 }
136 151
137 /// Returns the roots for the current `ProjectWorkspace` 152 /// Returns the roots for the current `ProjectWorkspace`
@@ -139,7 +154,7 @@ impl ProjectWorkspace {
139 /// the root is a member of the current workspace 154 /// the root is a member of the current workspace
140 pub fn to_roots(&self) -> Vec<PackageRoot> { 155 pub fn to_roots(&self) -> Vec<PackageRoot> {
141 match self { 156 match self {
142 ProjectWorkspace::Json { project, sysroot } => project 157 ProjectWorkspace::Json { project, sysroot, rustc_cfg: _ } => project
143 .crates() 158 .crates()
144 .map(|(_, krate)| PackageRoot { 159 .map(|(_, krate)| PackageRoot {
145 is_member: krate.is_workspace_member, 160 is_member: krate.is_workspace_member,
@@ -156,7 +171,7 @@ impl ProjectWorkspace {
156 }) 171 })
157 })) 172 }))
158 .collect::<Vec<_>>(), 173 .collect::<Vec<_>>(),
159 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => cargo 174 ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg: _ } => cargo
160 .packages() 175 .packages()
161 .map(|pkg| { 176 .map(|pkg| {
162 let is_member = cargo[pkg].is_member; 177 let is_member = cargo[pkg].is_member;
@@ -194,7 +209,7 @@ impl ProjectWorkspace {
194 pub fn n_packages(&self) -> usize { 209 pub fn n_packages(&self) -> usize {
195 match self { 210 match self {
196 ProjectWorkspace::Json { project, .. } => project.n_crates(), 211 ProjectWorkspace::Json { project, .. } => project.n_crates(),
197 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => { 212 ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => {
198 let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len()); 213 let rustc_package_len = rustc.as_ref().map_or(0, |rc| rc.packages().len());
199 cargo.packages().len() + sysroot.crates().len() + rustc_package_len 214 cargo.packages().len() + sysroot.crates().len() + rustc_package_len
200 } 215 }
@@ -203,22 +218,31 @@ impl ProjectWorkspace {
203 218
204 pub fn to_crate_graph( 219 pub fn to_crate_graph(
205 &self, 220 &self,
206 target: Option<&str>,
207 proc_macro_client: Option<&ProcMacroClient>, 221 proc_macro_client: Option<&ProcMacroClient>,
208 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 222 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
209 ) -> CrateGraph { 223 ) -> CrateGraph {
224 let _p = profile::span("ProjectWorkspace::to_crate_graph");
210 let proc_macro_loader = |path: &Path| match proc_macro_client { 225 let proc_macro_loader = |path: &Path| match proc_macro_client {
211 Some(client) => client.by_dylib_path(path), 226 Some(client) => client.by_dylib_path(path),
212 None => Vec::new(), 227 None => Vec::new(),
213 }; 228 };
214 229
215 let mut crate_graph = match self { 230 let mut crate_graph = match self {
216 ProjectWorkspace::Json { project, sysroot } => { 231 ProjectWorkspace::Json { project, sysroot, rustc_cfg } => project_json_to_crate_graph(
217 project_json_to_crate_graph(target, &proc_macro_loader, load, project, sysroot) 232 rustc_cfg.clone(),
218 } 233 &proc_macro_loader,
219 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => { 234 load,
220 cargo_to_crate_graph(target, &proc_macro_loader, load, cargo, sysroot, rustc) 235 project,
221 } 236 sysroot,
237 ),
238 ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => cargo_to_crate_graph(
239 rustc_cfg.clone(),
240 &proc_macro_loader,
241 load,
242 cargo,
243 sysroot,
244 rustc,
245 ),
222 }; 246 };
223 if crate_graph.patch_cfg_if() { 247 if crate_graph.patch_cfg_if() {
224 log::debug!("Patched std to depend on cfg-if") 248 log::debug!("Patched std to depend on cfg-if")
@@ -230,7 +254,7 @@ impl ProjectWorkspace {
230} 254}
231 255
232fn project_json_to_crate_graph( 256fn project_json_to_crate_graph(
233 target: Option<&str>, 257 rustc_cfg: Vec<CfgFlag>,
234 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, 258 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
235 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 259 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
236 project: &ProjectJson, 260 project: &ProjectJson,
@@ -239,9 +263,9 @@ fn project_json_to_crate_graph(
239 let mut crate_graph = CrateGraph::default(); 263 let mut crate_graph = CrateGraph::default();
240 let sysroot_deps = sysroot 264 let sysroot_deps = sysroot
241 .as_ref() 265 .as_ref()
242 .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load)); 266 .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load));
243 267
244 let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); 268 let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
245 let crates: FxHashMap<CrateId, CrateId> = project 269 let crates: FxHashMap<CrateId, CrateId> = project
246 .crates() 270 .crates()
247 .filter_map(|(crate_id, krate)| { 271 .filter_map(|(crate_id, krate)| {
@@ -253,9 +277,12 @@ fn project_json_to_crate_graph(
253 let env = krate.env.clone().into_iter().collect(); 277 let env = krate.env.clone().into_iter().collect();
254 let proc_macro = krate.proc_macro_dylib_path.clone().map(|it| proc_macro_loader(&it)); 278 let proc_macro = krate.proc_macro_dylib_path.clone().map(|it| proc_macro_loader(&it));
255 279
256 let target = krate.target.as_deref().or(target); 280 let target_cfgs = match krate.target.as_deref() {
257 let target_cfgs = 281 Some(target) => {
258 cfg_cache.entry(target).or_insert_with(|| get_rustc_cfg_options(target)); 282 cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(Some(target)))
283 }
284 None => &rustc_cfg,
285 };
259 286
260 let mut cfg_options = CfgOptions::default(); 287 let mut cfg_options = CfgOptions::default();
261 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); 288 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
@@ -292,19 +319,20 @@ fn project_json_to_crate_graph(
292} 319}
293 320
294fn cargo_to_crate_graph( 321fn cargo_to_crate_graph(
295 target: Option<&str>, 322 rustc_cfg: Vec<CfgFlag>,
296 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, 323 proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
297 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 324 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
298 cargo: &CargoWorkspace, 325 cargo: &CargoWorkspace,
299 sysroot: &Sysroot, 326 sysroot: &Sysroot,
300 rustc: &Option<CargoWorkspace>, 327 rustc: &Option<CargoWorkspace>,
301) -> CrateGraph { 328) -> CrateGraph {
329 let _p = profile::span("cargo_to_crate_graph");
302 let mut crate_graph = CrateGraph::default(); 330 let mut crate_graph = CrateGraph::default();
303 let (public_deps, libproc_macro) = 331 let (public_deps, libproc_macro) =
304 sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load); 332 sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
305 333
306 let mut cfg_options = CfgOptions::default(); 334 let mut cfg_options = CfgOptions::default();
307 cfg_options.extend(get_rustc_cfg_options(target)); 335 cfg_options.extend(rustc_cfg);
308 336
309 let mut pkg_to_lib_crate = FxHashMap::default(); 337 let mut pkg_to_lib_crate = FxHashMap::default();
310 338
@@ -490,11 +518,12 @@ fn add_target_crate_root(
490fn sysroot_to_crate_graph( 518fn sysroot_to_crate_graph(
491 crate_graph: &mut CrateGraph, 519 crate_graph: &mut CrateGraph,
492 sysroot: &Sysroot, 520 sysroot: &Sysroot,
493 target: Option<&str>, 521 rustc_cfg: Vec<CfgFlag>,
494 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 522 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
495) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { 523) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
524 let _p = profile::span("sysroot_to_crate_graph");
496 let mut cfg_options = CfgOptions::default(); 525 let mut cfg_options = CfgOptions::default();
497 cfg_options.extend(get_rustc_cfg_options(target)); 526 cfg_options.extend(rustc_cfg);
498 let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = sysroot 527 let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = sysroot
499 .crates() 528 .crates()
500 .filter_map(|krate| { 529 .filter_map(|krate| {
@@ -533,34 +562,6 @@ fn sysroot_to_crate_graph(
533 (public_deps, libproc_macro) 562 (public_deps, libproc_macro)
534} 563}
535 564
536fn get_rustc_cfg_options(target: Option<&str>) -> Vec<CfgFlag> {
537 let mut res = Vec::new();
538
539 // Some nightly-only cfgs, which are required for stdlib
540 res.push(CfgFlag::Atom("target_thread_local".into()));
541 for &ty in ["8", "16", "32", "64", "cas", "ptr"].iter() {
542 for &key in ["target_has_atomic", "target_has_atomic_load_store"].iter() {
543 res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() });
544 }
545 }
546
547 let rustc_cfgs = {
548 let mut cmd = Command::new(toolchain::rustc());
549 cmd.args(&["--print", "cfg", "-O"]);
550 if let Some(target) = target {
551 cmd.args(&["--target", target]);
552 }
553 utf8_stdout(cmd)
554 };
555
556 match rustc_cfgs {
557 Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())),
558 Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
559 }
560
561 res
562}
563
564fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) { 565fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
565 if let Err(err) = graph.add_dep(from, name, to) { 566 if let Err(err) = graph.add_dep(from, name, to) {
566 log::error!("{}", err) 567 log::error!("{}", err)
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index af7b86ead..3cb45b030 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -61,8 +61,14 @@ proc_macro_srv = { path = "../proc_macro_srv", version = "0.0.0" }
61[target.'cfg(windows)'.dependencies] 61[target.'cfg(windows)'.dependencies]
62winapi = "0.3.8" 62winapi = "0.3.8"
63 63
64[target.'cfg(not(target_env = "msvc"))'.dependencies]
65jemallocator = { version = "0.3.2", optional = true }
66
64[dev-dependencies] 67[dev-dependencies]
65expect-test = "1.1" 68expect-test = "1.1"
66test_utils = { path = "../test_utils" } 69test_utils = { path = "../test_utils" }
67mbe = { path = "../mbe" } 70mbe = { path = "../mbe" }
68tt = { path = "../tt" } 71tt = { path = "../tt" }
72
73[features]
74jemalloc = ["jemallocator", "profile/jemalloc"]
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index bf42654a8..2f7f94a39 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -15,6 +15,10 @@ use vfs::AbsPathBuf;
15#[global_allocator] 15#[global_allocator]
16static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; 16static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
17 17
18#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))]
19#[global_allocator]
20static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
21
18fn main() { 22fn main() {
19 if let Err(err) = try_main() { 23 if let Err(err) = try_main() {
20 eprintln!("{}", err); 24 eprintln!("{}", err);
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 31a16ca46..16ccab781 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -39,7 +39,7 @@ pub fn load_cargo(
39 None 39 None
40 }; 40 };
41 41
42 let crate_graph = ws.to_crate_graph(None, proc_macro_client.as_ref(), &mut |path: &AbsPath| { 42 let crate_graph = ws.to_crate_graph(proc_macro_client.as_ref(), &mut |path: &AbsPath| {
43 let contents = loader.load_sync(path); 43 let contents = loader.load_sync(path);
44 let path = vfs::VfsPath::from(path.to_path_buf()); 44 let path = vfs::VfsPath::from(path.to_path_buf());
45 vfs.set_file_contents(path.clone(), contents); 45 vfs.set_file_contents(path.clone(), contents);
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index a19e9e7dc..001f3a37d 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -810,7 +810,7 @@ pub(crate) fn handle_rename(
810 810
811 let change = 811 let change =
812 snap.analysis.rename(position, &*params.new_name)?.map_err(to_proto::rename_error)?; 812 snap.analysis.rename(position, &*params.new_name)?.map_err(to_proto::rename_error)?;
813 let workspace_edit = to_proto::workspace_edit(&snap, change.info)?; 813 let workspace_edit = to_proto::workspace_edit(&snap, change)?;
814 Ok(Some(workspace_edit)) 814 Ok(Some(workspace_edit))
815} 815}
816 816
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 97e20362f..dabfb4241 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -135,7 +135,10 @@ impl GlobalState {
135 ) 135 )
136 } 136 }
137 LinkedProject::InlineJsonProject(it) => { 137 LinkedProject::InlineJsonProject(it) => {
138 project_model::ProjectWorkspace::load_inline(it.clone()) 138 project_model::ProjectWorkspace::load_inline(
139 it.clone(),
140 cargo_config.target.as_deref(),
141 )
139 } 142 }
140 }) 143 })
141 .collect::<Vec<_>>(); 144 .collect::<Vec<_>>();
@@ -253,11 +256,7 @@ impl GlobalState {
253 res 256 res
254 }; 257 };
255 for ws in workspaces.iter() { 258 for ws in workspaces.iter() {
256 crate_graph.extend(ws.to_crate_graph( 259 crate_graph.extend(ws.to_crate_graph(self.proc_macro_client.as_ref(), &mut load));
257 self.config.cargo().target.as_deref(),
258 self.proc_macro_client.as_ref(),
259 &mut load,
260 ));
261 } 260 }
262 261
263 crate_graph 262 crate_graph
@@ -274,6 +273,7 @@ impl GlobalState {
274 } 273 }
275 274
276 fn reload_flycheck(&mut self) { 275 fn reload_flycheck(&mut self) {
276 let _p = profile::span("GlobalState::reload_flycheck");
277 let config = match self.config.flycheck() { 277 let config = match self.config.flycheck() {
278 Some(it) => it, 278 Some(it) => it,
279 None => { 279 None => {
@@ -288,9 +288,7 @@ impl GlobalState {
288 .iter() 288 .iter()
289 .enumerate() 289 .enumerate()
290 .filter_map(|(id, w)| match w { 290 .filter_map(|(id, w)| match w {
291 ProjectWorkspace::Cargo { cargo, sysroot: _, rustc: _ } => { 291 ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())),
292 Some((id, cargo.workspace_root()))
293 }
294 ProjectWorkspace::Json { project, .. } => { 292 ProjectWorkspace::Json { project, .. } => {
295 // Enable flychecks for json projects if a custom flycheck command was supplied 293 // Enable flychecks for json projects if a custom flycheck command was supplied
296 // in the workspace configuration. 294 // in the workspace configuration.
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index ad8b797fe..52394b337 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12 12
13[dependencies] 13[dependencies]
14itertools = "0.10.0" 14itertools = "0.10.0"
15rowan = "0.10.1" 15rowan = "0.10.3"
16rustc_lexer = { version = "697.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "697.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 1d722db3c..5baa54a3f 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -11,6 +11,7 @@ pub struct Name {
11} 11}
12impl Name { 12impl Name {
13 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } 13 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
14 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
14} 15}
15#[derive(Debug, Clone, PartialEq, Eq, Hash)] 16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct NameRef { 17pub struct NameRef {
@@ -238,7 +239,6 @@ impl ExternCrate {
238 pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) } 239 pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
239 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } 240 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
240 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } 241 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
241 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
242 pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) } 242 pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
243 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 243 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
244} 244}
@@ -406,9 +406,6 @@ pub struct Visibility {
406impl Visibility { 406impl Visibility {
407 pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) } 407 pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
408 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } 408 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
409 pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
410 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
411 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
412 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } 409 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
413 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 410 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
414 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 411 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
@@ -492,11 +489,11 @@ pub struct SelfParam {
492 pub(crate) syntax: SyntaxNode, 489 pub(crate) syntax: SyntaxNode,
493} 490}
494impl ast::AttrsOwner for SelfParam {} 491impl ast::AttrsOwner for SelfParam {}
492impl ast::NameOwner for SelfParam {}
495impl SelfParam { 493impl SelfParam {
496 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } 494 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
497 pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) } 495 pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
498 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 496 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
499 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
500 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } 497 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
501 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } 498 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
502} 499}
@@ -1075,6 +1072,13 @@ impl InferType {
1075 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } 1072 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
1076} 1073}
1077#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1074#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1075pub struct MacroType {
1076 pub(crate) syntax: SyntaxNode,
1077}
1078impl MacroType {
1079 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
1080}
1081#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1078pub struct NeverType { 1082pub struct NeverType {
1079 pub(crate) syntax: SyntaxNode, 1083 pub(crate) syntax: SyntaxNode,
1080} 1084}
@@ -1303,6 +1307,7 @@ pub enum Type {
1303 ForType(ForType), 1307 ForType(ForType),
1304 ImplTraitType(ImplTraitType), 1308 ImplTraitType(ImplTraitType),
1305 InferType(InferType), 1309 InferType(InferType),
1310 MacroType(MacroType),
1306 NeverType(NeverType), 1311 NeverType(NeverType),
1307 ParenType(ParenType), 1312 ParenType(ParenType),
1308 PathType(PathType), 1313 PathType(PathType),
@@ -2561,6 +2566,17 @@ impl AstNode for InferType {
2561 } 2566 }
2562 fn syntax(&self) -> &SyntaxNode { &self.syntax } 2567 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2563} 2568}
2569impl AstNode for MacroType {
2570 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_TYPE }
2571 fn cast(syntax: SyntaxNode) -> Option<Self> {
2572 if Self::can_cast(syntax.kind()) {
2573 Some(Self { syntax })
2574 } else {
2575 None
2576 }
2577 }
2578 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2579}
2564impl AstNode for NeverType { 2580impl AstNode for NeverType {
2565 fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE } 2581 fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
2566 fn cast(syntax: SyntaxNode) -> Option<Self> { 2582 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2892,6 +2908,9 @@ impl From<ImplTraitType> for Type {
2892impl From<InferType> for Type { 2908impl From<InferType> for Type {
2893 fn from(node: InferType) -> Type { Type::InferType(node) } 2909 fn from(node: InferType) -> Type { Type::InferType(node) }
2894} 2910}
2911impl From<MacroType> for Type {
2912 fn from(node: MacroType) -> Type { Type::MacroType(node) }
2913}
2895impl From<NeverType> for Type { 2914impl From<NeverType> for Type {
2896 fn from(node: NeverType) -> Type { Type::NeverType(node) } 2915 fn from(node: NeverType) -> Type { Type::NeverType(node) }
2897} 2916}
@@ -2917,8 +2936,8 @@ impl AstNode for Type {
2917 fn can_cast(kind: SyntaxKind) -> bool { 2936 fn can_cast(kind: SyntaxKind) -> bool {
2918 match kind { 2937 match kind {
2919 ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE 2938 ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE
2920 | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE | SLICE_TYPE 2939 | MACRO_TYPE | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE
2921 | TUPLE_TYPE => true, 2940 | SLICE_TYPE | TUPLE_TYPE => true,
2922 _ => false, 2941 _ => false,
2923 } 2942 }
2924 } 2943 }
@@ -2930,6 +2949,7 @@ impl AstNode for Type {
2930 FOR_TYPE => Type::ForType(ForType { syntax }), 2949 FOR_TYPE => Type::ForType(ForType { syntax }),
2931 IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }), 2950 IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
2932 INFER_TYPE => Type::InferType(InferType { syntax }), 2951 INFER_TYPE => Type::InferType(InferType { syntax }),
2952 MACRO_TYPE => Type::MacroType(MacroType { syntax }),
2933 NEVER_TYPE => Type::NeverType(NeverType { syntax }), 2953 NEVER_TYPE => Type::NeverType(NeverType { syntax }),
2934 PAREN_TYPE => Type::ParenType(ParenType { syntax }), 2954 PAREN_TYPE => Type::ParenType(ParenType { syntax }),
2935 PATH_TYPE => Type::PathType(PathType { syntax }), 2955 PATH_TYPE => Type::PathType(PathType { syntax }),
@@ -2949,6 +2969,7 @@ impl AstNode for Type {
2949 Type::ForType(it) => &it.syntax, 2969 Type::ForType(it) => &it.syntax,
2950 Type::ImplTraitType(it) => &it.syntax, 2970 Type::ImplTraitType(it) => &it.syntax,
2951 Type::InferType(it) => &it.syntax, 2971 Type::InferType(it) => &it.syntax,
2972 Type::MacroType(it) => &it.syntax,
2952 Type::NeverType(it) => &it.syntax, 2973 Type::NeverType(it) => &it.syntax,
2953 Type::ParenType(it) => &it.syntax, 2974 Type::ParenType(it) => &it.syntax,
2954 Type::PathType(it) => &it.syntax, 2975 Type::PathType(it) => &it.syntax,
@@ -4085,6 +4106,11 @@ impl std::fmt::Display for InferType {
4085 std::fmt::Display::fmt(self.syntax(), f) 4106 std::fmt::Display::fmt(self.syntax(), f)
4086 } 4107 }
4087} 4108}
4109impl std::fmt::Display for MacroType {
4110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4111 std::fmt::Display::fmt(self.syntax(), f)
4112 }
4113}
4088impl std::fmt::Display for NeverType { 4114impl std::fmt::Display for NeverType {
4089 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 4115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4090 std::fmt::Display::fmt(self.syntax(), f) 4116 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index b8ce71d27..738c92a5b 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -198,6 +198,13 @@ impl ast::Path {
198 pub fn parent_path(&self) -> Option<ast::Path> { 198 pub fn parent_path(&self) -> Option<ast::Path> {
199 self.syntax().parent().and_then(ast::Path::cast) 199 self.syntax().parent().and_then(ast::Path::cast)
200 } 200 }
201
202 pub fn as_single_segment(&self) -> Option<ast::PathSegment> {
203 match self.qualifier() {
204 Some(_) => None,
205 None => self.segment(),
206 }
207 }
201} 208}
202 209
203impl ast::UseTreeList { 210impl ast::UseTreeList {
@@ -448,16 +455,22 @@ pub enum VisibilityKind {
448 455
449impl ast::Visibility { 456impl ast::Visibility {
450 pub fn kind(&self) -> VisibilityKind { 457 pub fn kind(&self) -> VisibilityKind {
451 if let Some(path) = support::children(self.syntax()).next() { 458 match self.path() {
452 VisibilityKind::In(path) 459 Some(path) => {
453 } else if self.crate_token().is_some() { 460 if let Some(segment) =
454 VisibilityKind::PubCrate 461 path.as_single_segment().filter(|it| it.coloncolon_token().is_none())
455 } else if self.super_token().is_some() { 462 {
456 VisibilityKind::PubSuper 463 if segment.crate_token().is_some() {
457 } else if self.self_token().is_some() { 464 return VisibilityKind::PubCrate;
458 VisibilityKind::PubSelf 465 } else if segment.super_token().is_some() {
459 } else { 466 return VisibilityKind::PubSuper;
460 VisibilityKind::Pub 467 } else if segment.self_token().is_some() {
468 return VisibilityKind::PubSelf;
469 }
470 }
471 VisibilityKind::In(path)
472 }
473 None => VisibilityKind::Pub,
461 } 474 }
462 } 475 }
463} 476}
diff --git a/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast
index faf87d6e5..ae4dd2f3b 100644
--- a/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast
+++ b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast
@@ -50,7 +50,10 @@ [email protected]
50 [email protected] 50 [email protected]
51 [email protected] "pub" 51 [email protected] "pub"
52 [email protected] "(" 52 [email protected] "("
53 [email protected] "crate" 53 [email protected]
54 [email protected]
55 [email protected]
56 [email protected] "crate"
54 [email protected] ")" 57 [email protected] ")"
55 [email protected] " " 58 [email protected] " "
56 [email protected] "type" 59 [email protected] "type"
@@ -69,7 +72,10 @@ [email protected]
69 [email protected] 72 [email protected]
70 [email protected] "pub" 73 [email protected] "pub"
71 [email protected] "(" 74 [email protected] "("
72 [email protected] "crate" 75 [email protected]
76 [email protected]
77 [email protected]
78 [email protected] "crate"
73 [email protected] ")" 79 [email protected] ")"
74 [email protected] " " 80 [email protected] " "
75 [email protected] "const" 81 [email protected] "const"
diff --git a/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast
index 8048f5fad..f0d152d33 100644
--- a/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast
@@ -19,7 +19,8 @@ [email protected]
19 [email protected] 19 [email protected]
20 [email protected] "(" 20 [email protected] "("
21 [email protected] 21 [email protected]
22 [email protected] "self" 22 [email protected]
23 [email protected] "self"
23 [email protected] ")" 24 [email protected] ")"
24 [email protected] " " 25 [email protected] " "
25 [email protected] 26 [email protected]
@@ -35,7 +36,8 @@ [email protected]
35 [email protected] "(" 36 [email protected] "("
36 [email protected] 37 [email protected]
37 [email protected] "&" 38 [email protected] "&"
38 [email protected] "self" 39 [email protected]
40 [email protected] "self"
39 [email protected] "," 41 [email protected] ","
40 [email protected] ")" 42 [email protected] ")"
41 [email protected] " " 43 [email protected] " "
@@ -55,7 +57,8 @@ [email protected]
55 [email protected] 57 [email protected]
56 [email protected] "\'a" 58 [email protected] "\'a"
57 [email protected] " " 59 [email protected] " "
58 [email protected] "self" 60 [email protected]
61 [email protected] "self"
59 [email protected] "," 62 [email protected] ","
60 [email protected] ")" 63 [email protected] ")"
61 [email protected] " " 64 [email protected] " "
@@ -77,7 +80,8 @@ [email protected]
77 [email protected] " " 80 [email protected] " "
78 [email protected] "mut" 81 [email protected] "mut"
79 [email protected] " " 82 [email protected] " "
80 [email protected] "self" 83 [email protected]
84 [email protected] "self"
81 [email protected] "," 85 [email protected] ","
82 [email protected] " " 86 [email protected] " "
83 [email protected] 87 [email protected]
@@ -107,7 +111,8 @@ [email protected]
107 [email protected] 111 [email protected]
108 [email protected] "mut" 112 [email protected] "mut"
109 [email protected] " " 113 [email protected] " "
110 [email protected] "self" 114 [email protected]
115 [email protected] "self"
111 [email protected] ")" 116 [email protected] ")"
112 [email protected] " " 117 [email protected] " "
113 [email protected] 118 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
index ddbd66588..df59f37a2 100644
--- a/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
@@ -19,7 +19,8 @@ [email protected]
19 [email protected] 19 [email protected]
20 [email protected] "(" 20 [email protected] "("
21 [email protected] 21 [email protected]
22 [email protected] "self" 22 [email protected]
23 [email protected] "self"
23 [email protected] ":" 24 [email protected] ":"
24 [email protected] " " 25 [email protected] " "
25 [email protected] 26 [email protected]
@@ -45,7 +46,8 @@ [email protected]
45 [email protected] 46 [email protected]
46 [email protected] "mut" 47 [email protected] "mut"
47 [email protected] " " 48 [email protected] " "
48 [email protected] "self" 49 [email protected]
50 [email protected] "self"
49 [email protected] ":" 51 [email protected] ":"
50 [email protected] " " 52 [email protected] " "
51 [email protected] 53 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
index ca0702aba..dc7f6295b 100644
--- a/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
@@ -67,7 +67,8 @@ [email protected]
67 [email protected] "(" 67 [email protected] "("
68 [email protected] 68 [email protected]
69 [email protected] "&" 69 [email protected] "&"
70 [email protected] "self" 70 [email protected]
71 [email protected] "self"
71 [email protected] ")" 72 [email protected] ")"
72 [email protected] " " 73 [email protected] " "
73 [email protected] 74 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast
index 50742cbcf..f2ead8a62 100644
--- a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast
@@ -1,9 +1,12 @@
1SOURCE_FILE@0..81 1SOURCE_FILE@0..62
2 [email protected] 2 [email protected]
3 [email protected] 3 [email protected]
4 [email protected] "pub" 4 [email protected] "pub"
5 [email protected] "(" 5 [email protected] "("
6 [email protected] "crate" 6 [email protected]
7 [email protected]
8 [email protected]
9 [email protected] "crate"
7 [email protected] ")" 10 [email protected] ")"
8 [email protected] " " 11 [email protected] " "
9 [email protected] "struct" 12 [email protected] "struct"
@@ -16,7 +19,10 @@ [email protected]
16 [email protected] 19 [email protected]
17 [email protected] "pub" 20 [email protected] "pub"
18 [email protected] "(" 21 [email protected] "("
19 [email protected] "self" 22 [email protected]
23 [email protected]
24 [email protected]
25 [email protected] "self"
20 [email protected] ")" 26 [email protected] ")"
21 [email protected] " " 27 [email protected] " "
22 [email protected] "struct" 28 [email protected] "struct"
@@ -25,29 +31,19 @@ [email protected]
25 [email protected] "S" 31 [email protected] "S"
26 [email protected] ";" 32 [email protected] ";"
27 [email protected] "\n" 33 [email protected] "\n"
28 [email protected]0 34 [email protected]1
29 [email protected]0 35 [email protected]1
30 [email protected] "pub" 36 [email protected] "pub"
31 [email protected] "(" 37 [email protected] "("
32 [email protected] "self" 38 [email protected]
33 [email protected] ")" 39 [email protected]
34 [email protected] " " 40 [email protected]
35 [email protected] "struct" 41 [email protected] "super"
36 [email protected] " " 42 [email protected] ")"
37 [email protected] 43 [email protected] " "
38 [email protected] "S" 44 [email protected] "struct"
39 [email protected] ";" 45 [email protected] " "
40 [email protected] "\n" 46 [email protected]
41 [email protected] 47 [email protected] "S"
42 [email protected] 48 [email protected] ";"
43 [email protected] "pub" 49 [email protected] "\n"
44 [email protected] "("
45 [email protected] "self"
46 [email protected] ")"
47 [email protected] " "
48 [email protected] "struct"
49 [email protected] " "
50 [email protected]
51 [email protected] "S"
52 [email protected] ";"
53 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs
index faeefde94..a790a485f 100644
--- a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs
+++ b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs
@@ -1,4 +1,3 @@
1pub(crate) struct S; 1pub(crate) struct S;
2pub(self) struct S; 2pub(self) struct S;
3pub(self) struct S; 3pub(super) struct S;
4pub(self) struct S;
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
index d3219f0b2..c54e64e3f 100644
--- a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
@@ -16,7 +16,8 @@ [email protected]
16 [email protected] "must_use" 16 [email protected] "must_use"
17 [email protected] "]" 17 [email protected] "]"
18 [email protected] " " 18 [email protected] " "
19 [email protected] "self" 19 [email protected]
20 [email protected] "self"
20 [email protected] ")" 21 [email protected] ")"
21 [email protected] " " 22 [email protected] " "
22 [email protected] 23 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rast b/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rast
new file mode 100644
index 000000000..3d855fc6b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rast
@@ -0,0 +1,42 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected] "pub"
5 [email protected] "("
6 [email protected] "in"
7 [email protected] " "
8 [email protected]
9 [email protected]
10 [email protected]
11 [email protected]
12 [email protected] "super"
13 [email protected] "::"
14 [email protected]
15 [email protected]
16 [email protected] "A"
17 [email protected] ")"
18 [email protected] " "
19 [email protected] "struct"
20 [email protected] " "
21 [email protected]
22 [email protected] "S"
23 [email protected] ";"
24 [email protected] "\n"
25 [email protected]
26 [email protected]
27 [email protected] "pub"
28 [email protected] "("
29 [email protected] "in"
30 [email protected] " "
31 [email protected]
32 [email protected]
33 [email protected]
34 [email protected] "crate"
35 [email protected] ")"
36 [email protected] " "
37 [email protected] "struct"
38 [email protected] " "
39 [email protected]
40 [email protected] "S"
41 [email protected] ";"
42 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rs b/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rs
new file mode 100644
index 000000000..2856dbd84
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0160_crate_visibility_in.rs
@@ -0,0 +1,2 @@
1pub(in super::A) struct S;
2pub(in crate) struct S;
diff --git a/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rast b/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rast
new file mode 100644
index 000000000..dcd39535b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rast
@@ -0,0 +1,24 @@
1[email protected]
2 [email protected]
3 [email protected] "impl"
4 [email protected] " "
5 [email protected] "const"
6 [email protected] " "
7 [email protected]
8 [email protected]
9 [email protected]
10 [email protected]
11 [email protected] "Send"
12 [email protected] " "
13 [email protected] "for"
14 [email protected] " "
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected] "X"
20 [email protected] " "
21 [email protected]
22 [email protected] "{"
23 [email protected] "}"
24 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rs b/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rs
new file mode 100644
index 000000000..8d6886469
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0161_impl_def_const.rs
@@ -0,0 +1 @@
impl const Send for X {}
diff --git a/crates/syntax/test_data/parser/ok/0007_extern_crate.rast b/crates/syntax/test_data/parser/ok/0007_extern_crate.rast
index 594c2f8f2..4babdba92 100644
--- a/crates/syntax/test_data/parser/ok/0007_extern_crate.rast
+++ b/crates/syntax/test_data/parser/ok/0007_extern_crate.rast
@@ -28,7 +28,8 @@ [email protected]
28 [email protected] " " 28 [email protected] " "
29 [email protected] "crate" 29 [email protected] "crate"
30 [email protected] " " 30 [email protected] " "
31 [email protected] "self" 31 [email protected]
32 [email protected] "self"
32 [email protected] " " 33 [email protected] " "
33 [email protected] 34 [email protected]
34 [email protected] "as" 35 [email protected] "as"
diff --git a/crates/syntax/test_data/parser/ok/0012_visibility.rast b/crates/syntax/test_data/parser/ok/0012_visibility.rast
index 83a93b5a9..c5dbfb702 100644
--- a/crates/syntax/test_data/parser/ok/0012_visibility.rast
+++ b/crates/syntax/test_data/parser/ok/0012_visibility.rast
@@ -32,7 +32,10 @@ [email protected]
32 [email protected] 32 [email protected]
33 [email protected] "pub" 33 [email protected] "pub"
34 [email protected] "(" 34 [email protected] "("
35 [email protected] "crate" 35 [email protected]
36 [email protected]
37 [email protected]
38 [email protected] "crate"
36 [email protected] ")" 39 [email protected] ")"
37 [email protected] " " 40 [email protected] " "
38 [email protected] "fn" 41 [email protected] "fn"
@@ -51,7 +54,10 @@ [email protected]
51 [email protected] 54 [email protected]
52 [email protected] "pub" 55 [email protected] "pub"
53 [email protected] "(" 56 [email protected] "("
54 [email protected] "super" 57 [email protected]
58 [email protected]
59 [email protected]
60 [email protected] "super"
55 [email protected] ")" 61 [email protected] ")"
56 [email protected] " " 62 [email protected] " "
57 [email protected] "fn" 63 [email protected] "fn"
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
index 0ac56df6d..6afed5f05 100644
--- a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
+++ b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
@@ -110,7 +110,8 @@ [email protected]
110 [email protected] "(" 110 [email protected] "("
111 [email protected] 111 [email protected]
112 [email protected] "&" 112 [email protected] "&"
113 [email protected] "self" 113 [email protected]
114 [email protected] "self"
114 [email protected] "," 115 [email protected] ","
115 [email protected] " " 116 [email protected] " "
116 [email protected] 117 [email protected]
diff --git a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
index 3fed11838..e10521d85 100644
--- a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
@@ -281,7 +281,8 @@ [email protected]
281 [email protected] "must_use" 281 [email protected] "must_use"
282 [email protected] "]" 282 [email protected] "]"
283 [email protected] " " 283 [email protected] " "
284 [email protected] "self" 284 [email protected]
285 [email protected] "self"
285 [email protected] ")" 286 [email protected] ")"
286 [email protected] " " 287 [email protected] " "
287 [email protected] 288 [email protected]
@@ -305,7 +306,8 @@ [email protected]
305 [email protected] "attr" 306 [email protected] "attr"
306 [email protected] "]" 307 [email protected] "]"
307 [email protected] " " 308 [email protected] " "
308 [email protected] "self" 309 [email protected]
310 [email protected] "self"
309 [email protected] ")" 311 [email protected] ")"
310 [email protected] " " 312 [email protected] " "
311 [email protected] 313 [email protected]
@@ -330,7 +332,8 @@ [email protected]
330 [email protected] "]" 332 [email protected] "]"
331 [email protected] " " 333 [email protected] " "
332 [email protected] "&" 334 [email protected] "&"
333 [email protected] "self" 335 [email protected]
336 [email protected] "self"
334 [email protected] ")" 337 [email protected] ")"
335 [email protected] " " 338 [email protected] " "
336 [email protected] 339 [email protected]
@@ -363,7 +366,8 @@ [email protected]
363 [email protected] "&" 366 [email protected] "&"
364 [email protected] "mut" 367 [email protected] "mut"
365 [email protected] " " 368 [email protected] " "
366 [email protected] "self" 369 [email protected]
370 [email protected] "self"
367 [email protected] ")" 371 [email protected] ")"
368 [email protected] " " 372 [email protected] " "
369 [email protected] 373 [email protected]
@@ -397,7 +401,8 @@ [email protected]
397 [email protected] 401 [email protected]
398 [email protected] "\'a" 402 [email protected] "\'a"
399 [email protected] " " 403 [email protected] " "
400 [email protected] "self" 404 [email protected]
405 [email protected] "self"
401 [email protected] ")" 406 [email protected] ")"
402 [email protected] " " 407 [email protected] " "
403 [email protected] 408 [email protected]
@@ -433,7 +438,8 @@ [email protected]
433 [email protected] " " 438 [email protected] " "
434 [email protected] "mut" 439 [email protected] "mut"
435 [email protected] " " 440 [email protected] " "
436 [email protected] "self" 441 [email protected]
442 [email protected] "self"
437 [email protected] ")" 443 [email protected] ")"
438 [email protected] " " 444 [email protected] " "
439 [email protected] 445 [email protected]
@@ -457,7 +463,8 @@ [email protected]
457 [email protected] "attr" 463 [email protected] "attr"
458 [email protected] "]" 464 [email protected] "]"
459 [email protected] " " 465 [email protected] " "
460 [email protected] "self" 466 [email protected]
467 [email protected] "self"
461 [email protected] ":" 468 [email protected] ":"
462 [email protected] " " 469 [email protected] " "
463 [email protected] 470 [email protected]
@@ -488,7 +495,8 @@ [email protected]
488 [email protected] "attr" 495 [email protected] "attr"
489 [email protected] "]" 496 [email protected] "]"
490 [email protected] " " 497 [email protected] " "
491 [email protected] "self" 498 [email protected]
499 [email protected] "self"
492 [email protected] ":" 500 [email protected] ":"
493 [email protected] " " 501 [email protected] " "
494 [email protected] 502 [email protected]
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index e598c2c84..1edb7713d 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -294,6 +294,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
294 "x64 linux": "x86_64-unknown-linux-gnu", 294 "x64 linux": "x86_64-unknown-linux-gnu",
295 "x64 darwin": "x86_64-apple-darwin", 295 "x64 darwin": "x86_64-apple-darwin",
296 "arm64 win32": "aarch64-pc-windows-msvc", 296 "arm64 win32": "aarch64-pc-windows-msvc",
297 "arm64 linux": "aarch64-unknown-linux-gnu",
297 "arm64 darwin": "aarch64-apple-darwin", 298 "arm64 darwin": "aarch64-apple-darwin",
298 }; 299 };
299 const platform = platforms[`${process.arch} ${process.platform}`]; 300 const platform = platforms[`${process.arch} ${process.platform}`];
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml
index b9dbb7ef3..f4d2ecb6c 100644
--- a/lib/arena/Cargo.toml
+++ b/lib/arena/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2name = "la-arena" 2name = "la-arena"
3version = "0.1.1" 3version = "0.2.0"
4description = "Simple index-based arena without deletion." 4description = "Simple index-based arena without deletion."
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6repository = "https://github.com/rust-analyzer/rust-analyzer" 6repository = "https://github.com/rust-analyzer/rust-analyzer"
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs
index 78a147c7d..230a50291 100644
--- a/lib/arena/src/lib.rs
+++ b/lib/arena/src/lib.rs
@@ -1,4 +1,4 @@
1//! Yet another ID-based arena. 1//! Yet another index-based arena.
2 2
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4 4
@@ -10,39 +10,40 @@ use std::{
10 ops::{Index, IndexMut}, 10 ops::{Index, IndexMut},
11}; 11};
12 12
13pub mod map; 13mod map;
14pub use map::ArenaMap;
14 15
15/// The raw ID of a value in an arena. 16/// The raw index of a value in an arena.
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct RawId(u32); 18pub struct RawIdx(u32);
18 19
19impl From<RawId> for u32 { 20impl From<RawIdx> for u32 {
20 fn from(raw: RawId) -> u32 { 21 fn from(raw: RawIdx) -> u32 {
21 raw.0 22 raw.0
22 } 23 }
23} 24}
24 25
25impl From<u32> for RawId { 26impl From<u32> for RawIdx {
26 fn from(id: u32) -> RawId { 27 fn from(idx: u32) -> RawIdx {
27 RawId(id) 28 RawIdx(idx)
28 } 29 }
29} 30}
30 31
31impl fmt::Debug for RawId { 32impl fmt::Debug for RawIdx {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 self.0.fmt(f) 34 self.0.fmt(f)
34 } 35 }
35} 36}
36 37
37impl fmt::Display for RawId { 38impl fmt::Display for RawIdx {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 self.0.fmt(f) 40 self.0.fmt(f)
40 } 41 }
41} 42}
42 43
43/// The ID of a value allocated in an arena that holds `T`s. 44/// The index of a value allocated in an arena that holds `T`s.
44pub struct Idx<T> { 45pub struct Idx<T> {
45 raw: RawId, 46 raw: RawIdx,
46 _ty: PhantomData<fn() -> T>, 47 _ty: PhantomData<fn() -> T>,
47} 48}
48 49
@@ -77,18 +78,18 @@ impl<T> fmt::Debug for Idx<T> {
77} 78}
78 79
79impl<T> Idx<T> { 80impl<T> Idx<T> {
80 /// Creates a new ID from a [`RawId`]. 81 /// Creates a new index from a [`RawIdx`].
81 pub fn from_raw(raw: RawId) -> Self { 82 pub fn from_raw(raw: RawIdx) -> Self {
82 Idx { raw, _ty: PhantomData } 83 Idx { raw, _ty: PhantomData }
83 } 84 }
84 85
85 /// Converts this ID into the underlying [`RawId`]. 86 /// Converts this index into the underlying [`RawIdx`].
86 pub fn into_raw(self) -> RawId { 87 pub fn into_raw(self) -> RawIdx {
87 self.raw 88 self.raw
88 } 89 }
89} 90}
90 91
91/// Yet another ID-based arena. 92/// Yet another index-based arena.
92#[derive(Clone, PartialEq, Eq)] 93#[derive(Clone, PartialEq, Eq)]
93pub struct Arena<T> { 94pub struct Arena<T> {
94 data: Vec<T>, 95 data: Vec<T>,
@@ -160,37 +161,37 @@ impl<T> Arena<T> {
160 self.data.is_empty() 161 self.data.is_empty()
161 } 162 }
162 163
163 /// Allocates a new value on the arena, returning the value’s ID. 164 /// Allocates a new value on the arena, returning the value’s index.
164 /// 165 ///
165 /// ``` 166 /// ```
166 /// let mut arena = la_arena::Arena::new(); 167 /// let mut arena = la_arena::Arena::new();
167 /// let id = arena.alloc(50); 168 /// let idx = arena.alloc(50);
168 /// 169 ///
169 /// assert_eq!(arena[id], 50); 170 /// assert_eq!(arena[idx], 50);
170 /// ``` 171 /// ```
171 pub fn alloc(&mut self, value: T) -> Idx<T> { 172 pub fn alloc(&mut self, value: T) -> Idx<T> {
172 let id = RawId(self.data.len() as u32); 173 let idx = RawIdx(self.data.len() as u32);
173 self.data.push(value); 174 self.data.push(value);
174 Idx::from_raw(id) 175 Idx::from_raw(idx)
175 } 176 }
176 177
177 /// Returns an iterator over the arena’s elements. 178 /// Returns an iterator over the arena’s elements.
178 /// 179 ///
179 /// ``` 180 /// ```
180 /// let mut arena = la_arena::Arena::new(); 181 /// let mut arena = la_arena::Arena::new();
181 /// let id1 = arena.alloc(20); 182 /// let idx1 = arena.alloc(20);
182 /// let id2 = arena.alloc(40); 183 /// let idx2 = arena.alloc(40);
183 /// let id3 = arena.alloc(60); 184 /// let idx3 = arena.alloc(60);
184 /// 185 ///
185 /// let mut iterator = arena.iter(); 186 /// let mut iterator = arena.iter();
186 /// assert_eq!(iterator.next(), Some((id1, &20))); 187 /// assert_eq!(iterator.next(), Some((idx1, &20)));
187 /// assert_eq!(iterator.next(), Some((id2, &40))); 188 /// assert_eq!(iterator.next(), Some((idx2, &40)));
188 /// assert_eq!(iterator.next(), Some((id3, &60))); 189 /// assert_eq!(iterator.next(), Some((idx3, &60)));
189 /// ``` 190 /// ```
190 pub fn iter( 191 pub fn iter(
191 &self, 192 &self,
192 ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator { 193 ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
193 self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value)) 194 self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value))
194 } 195 }
195 196
196 /// Reallocates the arena to make it take up as little space as possible. 197 /// Reallocates the arena to make it take up as little space as possible.
diff --git a/lib/arena/src/map.rs b/lib/arena/src/map.rs
index 980198247..d8acfe051 100644
--- a/lib/arena/src/map.rs
+++ b/lib/arena/src/map.rs
@@ -1,33 +1,34 @@
1//! A map from arena IDs to some other type. Space requirement is O(highest ID).
2
3use std::marker::PhantomData; 1use std::marker::PhantomData;
4 2
5use crate::Idx; 3use crate::Idx;
6 4
7/// A map from arena IDs to some other type. Space requirement is O(highest ID). 5/// A map from arena indexes to some other type.
6/// Space requirement is O(highest index).
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct ArenaMap<ID, V> { 8pub struct ArenaMap<IDX, V> {
10 v: Vec<Option<V>>, 9 v: Vec<Option<V>>,
11 _ty: PhantomData<ID>, 10 _ty: PhantomData<IDX>,
12} 11}
13 12
14impl<T, V> ArenaMap<Idx<T>, V> { 13impl<T, V> ArenaMap<Idx<T>, V> {
15 /// Inserts a value associated with a given arena ID into the map. 14 /// Inserts a value associated with a given arena index into the map.
16 pub fn insert(&mut self, id: Idx<T>, t: V) { 15 pub fn insert(&mut self, idx: Idx<T>, t: V) {
17 let idx = Self::to_idx(id); 16 let idx = Self::to_idx(idx);
18 17
19 self.v.resize_with((idx + 1).max(self.v.len()), || None); 18 self.v.resize_with((idx + 1).max(self.v.len()), || None);
20 self.v[idx] = Some(t); 19 self.v[idx] = Some(t);
21 } 20 }
22 21
23 /// Returns a reference to the value associated with the provided ID if it is present. 22 /// Returns a reference to the value associated with the provided index
24 pub fn get(&self, id: Idx<T>) -> Option<&V> { 23 /// if it is present.
25 self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) 24 pub fn get(&self, idx: Idx<T>) -> Option<&V> {
25 self.v.get(Self::to_idx(idx)).and_then(|it| it.as_ref())
26 } 26 }
27 27
28 /// Returns a mutable reference to the value associated with the provided ID if it is present. 28 /// Returns a mutable reference to the value associated with the provided index
29 pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> { 29 /// if it is present.
30 self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut()) 30 pub fn get_mut(&mut self, idx: Idx<T>) -> Option<&mut V> {
31 self.v.get_mut(Self::to_idx(idx)).and_then(|it| it.as_mut())
31 } 32 }
32 33
33 /// Returns an iterator over the values in the map. 34 /// Returns an iterator over the values in the map.
@@ -40,13 +41,13 @@ impl<T, V> ArenaMap<Idx<T>, V> {
40 self.v.iter_mut().filter_map(|o| o.as_mut()) 41 self.v.iter_mut().filter_map(|o| o.as_mut())
41 } 42 }
42 43
43 /// Returns an iterator over the arena IDs and values in the map. 44 /// Returns an iterator over the arena indexes and values in the map.
44 pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> { 45 pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> {
45 self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) 46 self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
46 } 47 }
47 48
48 fn to_idx(id: Idx<T>) -> usize { 49 fn to_idx(idx: Idx<T>) -> usize {
49 u32::from(id.into_raw()) as usize 50 u32::from(idx.into_raw()) as usize
50 } 51 }
51 52
52 fn from_idx(idx: usize) -> Idx<T> { 53 fn from_idx(idx: usize) -> Idx<T> {
@@ -56,8 +57,8 @@ impl<T, V> ArenaMap<Idx<T>, V> {
56 57
57impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> { 58impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> {
58 type Output = T; 59 type Output = T;
59 fn index(&self, id: Idx<V>) -> &T { 60 fn index(&self, idx: Idx<V>) -> &T {
60 self.v[Self::to_idx(id)].as_ref().unwrap() 61 self.v[Self::to_idx(idx)].as_ref().unwrap()
61 } 62 }
62} 63}
63 64
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 1bb9222d7..4abc7b053 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,7 +15,7 @@ flate2 = "1.0"
15pico-args = "0.3.1" 15pico-args = "0.3.1"
16proc-macro2 = "1.0.8" 16proc-macro2 = "1.0.8"
17quote = "1.0.2" 17quote = "1.0.2"
18ungrammar = "1.8" 18ungrammar = "1.9"
19walkdir = "2.3.1" 19walkdir = "2.3.1"
20write-json = "0.1.0" 20write-json = "0.1.0"
21xshell = "0.1" 21xshell = "0.1"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 046d68f52..0fd1d13e6 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -104,6 +104,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
104 "MACRO_DEF", 104 "MACRO_DEF",
105 "PAREN_TYPE", 105 "PAREN_TYPE",
106 "TUPLE_TYPE", 106 "TUPLE_TYPE",
107 "MACRO_TYPE",
107 "NEVER_TYPE", 108 "NEVER_TYPE",
108 "PATH_TYPE", 109 "PATH_TYPE",
109 "PTR_TYPE", 110 "PTR_TYPE",
diff --git a/xtask/src/install.rs b/xtask/src/install.rs
index 12962bcfa..202c74426 100644
--- a/xtask/src/install.rs
+++ b/xtask/src/install.rs
@@ -67,6 +67,7 @@ pub struct ServerOpt {
67pub enum Malloc { 67pub enum Malloc {
68 System, 68 System,
69 Mimalloc, 69 Mimalloc,
70 Jemalloc,
70} 71}
71 72
72impl InstallCmd { 73impl InstallCmd {
@@ -176,6 +177,7 @@ fn install_server(opts: ServerOpt) -> Result<()> {
176 let features = match opts.malloc { 177 let features = match opts.malloc {
177 Malloc::System => &[][..], 178 Malloc::System => &[][..],
178 Malloc::Mimalloc => &["--features", "mimalloc"], 179 Malloc::Mimalloc => &["--features", "mimalloc"],
180 Malloc::Jemalloc => &["--features", "jemalloc"],
179 }; 181 };
180 182
181 let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force {features...}"); 183 let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force {features...}");
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index dec48629c..c3e5c7326 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -49,7 +49,8 @@ FLAGS:
49 --client[=CLIENT] Install only VS Code plugin. 49 --client[=CLIENT] Install only VS Code plugin.
50 CLIENT is one of 'code', 'code-exploration', 'code-insiders', 'codium', or 'code-oss' 50 CLIENT is one of 'code', 'code-exploration', 'code-insiders', 'codium', or 'code-oss'
51 --server Install only the language server 51 --server Install only the language server
52 --mimalloc Use mimalloc for server 52 --mimalloc Use mimalloc allocator for server
53 --jemalloc Use jemalloc allocator for server
53 -h, --help Prints help information 54 -h, --help Prints help information
54 " 55 "
55 ); 56 );
@@ -65,8 +66,13 @@ FLAGS:
65 return Ok(()); 66 return Ok(());
66 } 67 }
67 68
68 let malloc = 69 let malloc = if args.contains("--mimalloc") {
69 if args.contains("--mimalloc") { Malloc::Mimalloc } else { Malloc::System }; 70 Malloc::Mimalloc
71 } else if args.contains("--jemalloc") {
72 Malloc::Jemalloc
73 } else {
74 Malloc::System
75 };
70 76
71 let client_opt = args.opt_value_from_str("--client")?; 77 let client_opt = args.opt_value_from_str("--client")?;
72 78