about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-31 02:24:44 +0000
committerbors <bors@rust-lang.org>2022-08-31 02:24:44 +0000
commit7f442f8ba174fd4233a14ef4d7b577aa907db594 (patch)
treee4825b3c7441ec0fab4d3aa6fee294d54e234b04 /src
parentf07d6e8c0a90a6b03dcf96366d0462c7c25962bd (diff)
parent0cbc58978b99c090673caa0f2c0e8b4bf7197ee3 (diff)
downloadrust-7f442f8ba174fd4233a14ef4d7b577aa907db594.tar.gz
rust-7f442f8ba174fd4233a14ef4d7b577aa907db594.zip
Auto merge of #101220 - JohnTitor:rollup-ov7upr7, r=JohnTitor
Rollup of 10 pull requests

Successful merges:

 - #100804 (Fix search results color on hover for ayu theme)
 - #100892 (Add `AsFd` implementations for stdio types on WASI.)
 - #100927 (Adding new Fuchsia rustup docs... reworking walkthrough)
 - #101088 (Set DebuginfoKind::Pdb in msvc_base)
 - #101159 (add tracking issue number to const_slice_split_at_not_mut)
 - #101192 (Remove path string)
 - #101193 (Avoid zeroing large stack buffers in stdio on Windows)
 - #101197 (:arrow_up: rust-analyzer)
 - #101200 (Add test for issue #85872)
 - #101219 (Update books)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
m---------src/doc/book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md523
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css7
-rw-r--r--src/test/codegen/issue-85872-multiple-reverse.rs20
-rw-r--r--src/test/rustdoc-gui/search-result-color.goml51
-rw-r--r--src/tools/rust-analyzer/Cargo.lock81
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs40
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs12
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs70
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs45
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs44
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs41
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/line_index.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/source_change.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs131
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/prime_caches.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs74
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast23
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast23
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast40
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs674
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs448
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs47
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs15
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs34
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs191
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs55
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/hash.rs80
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/vfs/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/file_set.rs3
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/lib.rs9
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc46
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc11
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json30
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts22
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts96
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts36
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/socket.rs2
82 files changed, 2486 insertions, 945 deletions
diff --git a/src/doc/book b/src/doc/book
-Subproject 42ca0ef484fcc8437a0682cee23abe4b7c407d5
+Subproject 0a5421ceb238357b3634fb75234eba4d1dad643
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 8e6aa3448515a0654e347b5e2510f1d4bc4d5a6
+Subproject d880e6ac2acf133dce640da24b9fb692844f02d
diff --git a/src/doc/reference b/src/doc/reference
-Subproject e647eb102890e8927f488bea12672b079eff8d9
+Subproject f62e93c28323ed9637d0a205a0c256498674a50
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d3daa1f28e169087becbc5e2b49ac91ca0405a4
+Subproject 04892c1a6fc145602ac7367945fda9d4ee83c9f
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 8b204949a6e..c2a1613f288 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -5,14 +5,10 @@
 [Fuchsia] is a modern open source operating system that's simple, secure,
 updatable, and performant.
 
-[Fuchsia]: https://fuchsia.dev/
-
 ## Target maintainers
 
 The [Fuchsia team]:
 
-[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
-
 - Tyler Mandry ([@tmandry](https://github.com/tmandry))
 - Dan Johnson ([@computerdruid](https://github.com/computerdruid))
 - David Koloski ([@djkoloski](https://github.com/djkoloski))
@@ -24,27 +20,162 @@ the members reported by the API. The API should be considered to be
 authoritative if this occurs. Instead of pinging individual members, use
 `@rustbot ping fuchsia` to contact the team on GitHub.
 
+## Table of contents
+
+1. [Requirements](#requirements)
+1. [Walkthrough structure](#walkthrough-structure)
+1. [Compiling a Rust binary targeting Fuchsia](#compiling-a-rust-binary-targeting-fuchsia)
+    1. [Targeting Fuchsia with rustup and cargo](#targeting-fuchsia-with-rustup-and-cargo)
+    1. [Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source)
+1. [Creating a Fuchsia package](#creating-a-fuchsia-package)
+    1. [Creating a Fuchsia component](#creating-a-fuchsia-component)
+    1. [Building a Fuchsia package](#building-a-fuchsia-package)
+1. [Publishing a Fuchsia package](#publishing-a-fuchsia-package)
+    1. [Creating a Fuchsia package repository](#creating-a-fuchsia-package-repository)
+    1. [Publishing Fuchsia package to repository](#publishing-fuchsia-package-to-repository)
+1. [Running a Fuchsia component on an emulator](#running-a-fuchsia-component-on-an-emulator)
+    1. [Starting the Fuchsia emulator](#starting-the-fuchsia-emulator)
+    1. [Watching emulator logs](#watching-emulator-logs)
+    1. [Serving a Fuchsia package](#serving-a-fuchsia-package)
+    1. [Running a Fuchsia component](#running-a-fuchsia-component)
+1. [`.gitignore` extensions](#gitignore-extensions)
+1. [Testing](#testing)
+    1. [Running unit tests](#running-unit-tests)
+    1. [Running the compiler test suite](#running-the-compiler-test-suite)
+
 ## Requirements
 
-This target is cross-compiled from a host environment. Development may be done
-from the [source tree] or using the Fuchsia SDK.
+This target is cross-compiled from a host environment. You will need a recent
+copy of the [Fuchsia SDK], which provides the tools, libraries, and binaries
+required to build and link programs for Fuchsia.
 
-[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
+Development may also be done from the [source tree].
 
-Fuchsia targets support std and follow the `sysv64` calling convention on
+Fuchsia targets support `std` and follow the `sysv64` calling convention on
 x86_64. Fuchsia binaries use the ELF file format.
 
-## Building the target
+## Walkthrough structure
+
+This walkthrough will cover:
+
+1. Compiling a Rust binary targeting Fuchsia.
+1. Building a Fuchsia package.
+1. Publishing and running a Fuchsia package to a Fuchsia emulator.
+
+For the purposes of this walkthrough, we will only target `x86_64-fuchsia`.
+
+## Compiling a Rust binary targeting Fuchsia
+
+Today, there are two main ways to build a Rust binary targeting Fuchsia
+using the Fuchsia SDK:
+1. Allow [rustup] to handle the installation of Fuchsia targets for you.
+1. Build a toolchain locally that can target Fuchsia.
+
+### Targeting Fuchsia with rustup and cargo
+
+The easiest way to build a Rust binary targeting Fuchsia is by allowing [rustup]
+to handle the installation of Fuchsia targets for you. This can be done by issuing
+the following commands:
+
+```sh
+rustup target add x86_64-fuchsia
+rustup target add aarch_64-fuchsia
+```
+
+After installing our Fuchsia targets, we can now compile a Rust binary that targets
+Fuchsia.
+
+To create our Rust project, we can issue a standard `cargo` command as follows:
+
+**From base working directory**
+```sh
+cargo new hello_fuchsia
+```
+
+The rest of this walkthrough will take place from `hello_fuchsia`, so we can
+change into that directory now:
+
+```sh
+cd hello_fuchsia
+```
+
+*Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
+directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
+
+We can edit our `src/main.rs` to include a test as follows:
+
+**`src/main.rs`**
+```rust
+fn main() {
+    println!("Hello Fuchsia!");
+}
+
+#[test]
+fn it_works() {
+    assert_eq!(2 + 2, 4);
+}
+```
+
+In addition to the standard workspace created, we will want to create a
+`.cargo/config.toml` file to link necessary libraries
+during compilation:
+
+**`.cargo/config.toml`**
+```txt
+[target.x86_64-fuchsia]
+
+rustflags = [
+    "-Lnative", "<SDK_PATH>/arch/x64/sysroot/lib",
+    "-Lnative", "<SDK_PATH>/arch/x64/lib"
+]
+```
+
+*Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
+
+In total, our new project will look like:
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┣━ src/
+┃  ┗━ main.rs
+┣━ Cargo.toml
+┗━ .cargo/
+   ┗━ config.toml
+```
+
+Finally, we can build our rust binary as:
+
+```sh
+cargo build --target x86_64-fuchsia
+```
+
+Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`,
+targeting our desired Fuchsia target.
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┣━ src/
+┃  ┗━ main.rs
+┣━ target/
+┃  ┗━ x86_64-fuchsia/
+┃     ┗━ debug/
+┃        ┗━ hello_fuchsia
+┣━ Cargo.toml
+┗━ .cargo/
+   ┗━ config.toml
+```
+
+### Targeting Fuchsia with a compiler built from source
+
+An alternative to the first workflow is to target Fuchsia by using
+`rustc` built from source.
 
 Before building Rust for Fuchsia, you'll need a clang toolchain that supports
 Fuchsia as well. A recent version (14+) of clang should be sufficient to compile
 Rust for Fuchsia.
 
-You'll also need a recent copy of the [Fuchsia SDK], which provides the tools
-and binaries required to build and link programs for Fuchsia.
-
-[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
-
 x86-64 and AArch64 Fuchsia targets can be enabled using the following
 configuration.
 
@@ -75,15 +206,21 @@ export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/
 These can be run together in a shell environment by executing
 `(source config-env.sh && ./x.py install)`.
 
-## Building Rust programs
+Once `rustc` is installed, we can create a new working directory to work from,
+`hello_fuchsia` along with `hello_fuchsia/src`:
 
-After compiling Rust binaries, you'll need to build a component, package it, and
-serve it to a Fuchsia device or emulator. All of this can be done using the
-Fuchsia SDK.
+```sh
+mkdir hello_fuchsia
+cd hello_fuchsia
+mkdir src
+```
 
-As an example, we'll compile and run this simple program on a Fuchsia emulator:
+*Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
+directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
 
-**`hello_fuchsia.rs`**
+There, we can create a new file named `src/hello_fuchsia.rs`:
+
+**`src/hello_fuchsia.rs`**
 ```rust
 fn main() {
     println!("Hello Fuchsia!");
@@ -95,31 +232,87 @@ fn it_works() {
 }
 ```
 
-Create a new file named `hello_fuchsia.rs` and fill out its contents with that
-code.
+**Current directory structure**
+```txt
+hello_fuchsia/
+┗━ src/
+    ┗━ hello_fuchsia.rs
+```
+
+Using your freshly installed `rustc`, you can compile a binary for Fuchsia using
+the following options:
+
+* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
+  platform of your choice
+* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
+  the SDK
+* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
+  libraries from the SDK
+
+Putting it all together:
+
+```sh
+# Configure these for the Fuchsia target of your choice
+TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
+ARCH="<x64|aarch64>"
+
+rustc \
+    --target ${TARGET_ARCH} \
+    -Lnative=${SDK_PATH}/arch/${ARCH}/lib \
+    -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib \
+    --out-dir bin src/hello_fuchsia.rs
+```
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┣━ src/
+┃   ┗━ hello_fuchsia.rs
+┗━ bin/
+   ┗━ hello_fuchsia
+```
+
+## Creating a Fuchsia package
 
-### Create a package
+Before moving on, double check your directory structure:
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┣━ src/                     (if using rustc)
+┃   ┗━ hello_fuchsia.rs     ...
+┣━ bin/                     ...
+┃  ┗━ hello_fuchsia         ...
+┣━ src/                     (if using cargo)
+┃  ┗━ main.rs               ...
+┗━ target/                  ...
+   ┗━ x86_64-fuchsia/       ...
+      ┗━ debug/             ...
+         ┗━ hello_fuchsia   ...
+```
 
+With our Rust binary built, we can move to creating a Fuchsia package.
 On Fuchsia, a package is the unit of distribution for software. We'll need to
 create a new package directory where we will place files like our finished
-binary and any data it may need. The working directory will have this layout:
+binary and any data it may need.
+
+To start, make the `pkg`, and `pkg/meta` directories:
+
+```sh
+mkdir pkg
+mkdir pkg/meta
+```
 
+**Current directory structure**
 ```txt
-hello_fuchsia.rs
-hello_fuchsia.cml
-package
-┣━ bin
-┃  ┗━ hello_fuchsia
-┣━ meta
-┃  ┣━ package
-┃  ┗━ hello_fuchsia.cm
-┗━ hello_fuchsia.manifest
+hello_fuchsia/
+┗━ pkg/
+   ┗━ meta/
 ```
 
-Make the `package`, `package/bin`, and `package/meta` directories and create the
-following files inside:
+Now, create the following files inside:
 
-**`package/meta/package`**
+**`pkg/meta/package`**
 ```json
 {
   "name": "hello_fuchsia",
@@ -130,13 +323,14 @@ following files inside:
 The `package` file describes our package's name and version number. Every
 package must contain one.
 
-**`package/hello_fuchsia.manifest`**
+**`pkg/hello_fuchsia.manifest`**
 ```txt
-bin/hello_fuchsia=package/bin/hello_fuchsia
+bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia     # If using cargo...
+bin/hello_fuchsia=bin/hello_fuchsia                             # If using rustc...
 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
-meta/package=package/meta/package
-meta/hello_fuchsia.cm=package/meta/hello_fuchsia.cm
+meta/package=pkg/meta/package
+meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
 ```
 
 *Note: Relative manifest paths are resolved starting from the working directory
@@ -144,42 +338,26 @@ of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
 SDK.*
 
 The `.manifest` file will be used to describe the contents of the package by
-relating their location when installed to their location on the file system. You
-can use this to make a package pull files from other places, but for this
-example we'll just be placing everything in the `package` directory.
-
-### Compiling a binary
-
-Using your freshly compiled `rustc`, you can compile a binary for Fuchsia using
-the following options:
-
-* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
-  platform of your choice
-* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
-  the SDK
-* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
-  libraries from the SDK
-
-Putting it all together:
-
-```sh
-# Configure these for the Fuchsia target of your choice
-TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
-ARCH="<x64|aarch64>"
+relating their location when installed to their location on the file system. The
+`bin/hello_fuchsia=` entry will be different depending on how your Rust binary
+was built, so choose accordingly.
 
-rustc --target ${TARGET_ARCH} -Lnative=${SDK_PATH}/arch/${ARCH}/lib -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib -o package/bin/hello_fuchsia hello_fuchsia.rs
+**Current directory structure**
+```txt
+hello_fuchsia/
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┗━ package
+   ┗━ hello_fuchsia.manifest
 ```
 
-### Bulding a component
+### Creating a Fuchsia component
 
-On Fuchsia, components require a component manifest written in Fuchia's markup
+On Fuchsia, components require a component manifest written in Fuchsia's markup
 language called CML. The Fuchsia devsite contains an [overview of CML] and a
 [reference for the file format]. Here's a basic one that can run our single binary:
 
-[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
-[reference for the file format]: https://fuchsia.dev/reference/cml
-
-**`hello_fuchsia.cml`**
+**`pkg/hello_fuchsia.cml`**
 ```txt
 {
     include: [ "syslog/client.shard.cml" ],
@@ -190,43 +368,152 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a
 }
 ```
 
+```txt
+hello_fuchsia/
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┗━ package
+   ┣━ hello_fuchsia.manifest
+   ┗━ hello_fuchsia.cml
+```
+
 Now we can compile that CML into a component manifest:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/cmc compile hello_fuchsia.cml --includepath ${SDK_PATH}/pkg -o package/meta/hello_fuchsia.cm
+${SDK_PATH}/tools/${ARCH}/cmc compile \
+    pkg/hello_fuchsia.cml \
+    --includepath ${SDK_PATH}/pkg \
+    -o pkg/meta/hello_fuchsia.cm
+```
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┣━ package
+   ┃  ┗━ hello_fuchsia.cm
+   ┣━ hello_fuchsia.manifest
+   ┗━ hello_fuchsia.cml
 ```
 
-`--includepath` tells the compiler where to look for `include`s from our CML.
-In our case, we're only using `syslog/client.shard.cml`.
+*Note: `--includepath` tells the compiler where to look for `include`s from our CML.
+In our case, we're only using `syslog/client.shard.cml`.*
 
-### Building and publishing a package
+### Building a Fuchsia package
 
-Next, we'll build our package as defined by our manifest:
+Next, we'll build a package manifest as defined by our manifest:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm -o hello_fuchsia -m package/hello_fuchsia.manifest build -output-package-manifest hello_fuchsia_manifest
+${SDK_PATH}/tools/${ARCH}/pm \
+    -o hello_fuchsia_manifest \
+    -m pkg/hello_fuchsia.manifest \
+    build \
+    -output-package-manifest hello_fuchsia_package_manifest
+```
+
+This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
+publish directly to a repository.
+
+**Current directory structure**
+```txt
+hello_fuchsia/
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┣━ package
+   ┃  ┗━ hello_fuchsia.cm
+   ┣━ hello_fuchsia_manifest/
+   ┃  ┗━ ...
+   ┣━ hello_fuchsia.manifest
+   ┣━ hello_fuchsia.cml
+   ┗━ hello_fuchsia_package_manifest
 ```
 
-This will produce `hello_fuchsia_manifest` which is a package manifest we can
-publish directly to a repository. We can set up that repository with:
+We are now ready to publish the package.
+
+## Publishing a Fuchsia package
+
+With our package and component manifests setup,
+we can now publish our package. The first step will
+be to create a Fuchsia package repository to publish
+to.
+
+### Creating a Fuchsia package repository
+
+We can set up our repository with:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm newrepo -repo repo
+${SDK_PATH}/tools/${ARCH}/pm newrepo \
+    -repo pkg/repo
 ```
 
-And then publish our new package to that repository with:
+**Current directory structure**
+```txt
+hello_fuchsia/
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┣━ package
+   ┃  ┗━ hello_fuchsia.cm
+   ┣━ hello_fuchsia_manifest/
+   ┃  ┗━ ...
+   ┣━ repo/
+   ┃  ┗━ ...
+   ┣━ hello_fuchsia.manifest
+   ┣━ hello_fuchsia.cml
+   ┗━ hello_fuchsia_package_manifest
+```
+
+## Publishing Fuchsia package to repository
+
+We can publish our new package to that repository with:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/pm publish -repo repo -lp -f <(echo "hello_fuchsia_manifest")
+${SDK_PATH}/tools/${ARCH}/pm publish \
+    -repo repo \
+    -lp -f <(echo "hello_fuchsia_package_manifest")
 ```
 
-Then we can add it to `ffx`'s package server as `hello-fuchsia` using:
+Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm repo -r hello-fuchsia
+${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
+    repo \
+    -r hello-fuchsia
+```
+
+## Running a Fuchsia component on an emulator
+
+At this point, we are ready to run our Fuchsia
+component. For reference, our final directory
+structure will look like:
+
+**Final directory structure**
+```txt
+hello_fuchsia/
+┣━ src/                     (if using rustc)
+┃   ┗━ hello_fuchsia.rs     ...
+┣━ bin/                     ...
+┃  ┗━ hello_fuchsia         ...
+┣━ src/                     (if using cargo)
+┃  ┗━ main.rs               ...
+┣━ target/                  ...
+┃  ┗━ x86_64-fuchsia/       ...
+┃     ┗━ debug/             ...
+┃        ┗━ hello_fuchsia   ...
+┗━ pkg/
+   ┣━ meta/
+   ┃  ┣━ package
+   ┃  ┗━ hello_fuchsia.cm
+   ┣━ hello_fuchsia_manifest/
+   ┃  ┗━ ...
+   ┣━ repo/
+   ┃  ┗━ ...
+   ┣━ hello_fuchsia.manifest
+   ┣━ hello_fuchsia.cml
+   ┗━ hello_fuchsia_package_manifest
 ```
 
-### Starting the emulator
+### Starting the Fuchsia emulator
 
 Start a Fuchsia emulator in a new terminal using:
 
@@ -235,50 +522,83 @@ ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
 ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
 ```
 
-Once the emulator is running, start a package repository server to serve our
-package to the emulator:
+### Watching emulator logs
 
+Once the emulator is running, open a separate terminal to watch the emulator logs:
+
+**In separate terminal**
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx repository server start
+${SDK_PATH}/tools/${ARCH}/ffx log \
+    --since now
 ```
 
-Once the repository server is up and running, register our repository:
+### Serving a Fuchsia package
+
+Now, start a package repository server to serve our
+package to the emulator:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx target repository register --repository hello-fuchsia
+${SDK_PATH}/tools/${ARCH}/ffx repository server start
 ```
 
-And watch the logs from the emulator in a separate terminal:
+Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx log --since now
+${SDK_PATH}/tools/${ARCH}/ffx target repository register \
+    --repository hello-fuchsia
 ```
 
+### Running a Fuchsia component
+
 Finally, run the component:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx component run fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm
+${SDK_PATH}/tools/${ARCH}/ffx component run \
+    fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
 ```
 
 On reruns of the component, the `--recreate` argument may also need to be
 passed.
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx component run --recreate fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm
+${SDK_PATH}/tools/${ARCH}/ffx component run \
+    --recreate \
+    fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
+```
+
+## `.gitignore` extensions
+
+Optionally, we can create/extend our `.gitignore` file to ignore files and
+directories that are not helpful to track:
+
+```txt
+pkg/repo
+pkg/meta/hello_fuchsia.cm
+pkg/hello_fuchsia_manifest
+pkg/hello_fuchsia_package_manifest
 ```
 
 ## Testing
 
 ### Running unit tests
 
-Tests can be run in the same way as a regular binary, simply by passing `--test`
-to the `rustc` invocation and then repackaging and rerunning. The test harness
-will run the applicable unit tests.
+Tests can be run in the same way as a regular binary.
+
+* If using `cargo`, you can simply pass `test --no-run`
+to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example,
+this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable
+binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
+into `pkg/hello_fuchsia.manifest`.
+
+* If using the compiled `rustc`, you can simply pass `--test`
+to the `rustc` invocation and then repackage and rerun the Fuchsia package.
+
+The test harness will run the applicable unit tests.
 
 Often when testing, you may want to pass additional command line arguments to
 your binary. Additional arguments can be set in the component manifest:
 
-**`hello_fuchsia.cml`**
+**`pkg/hello_fuchsia.cml`**
 ```txt
 {
     include: [ "syslog/client.shard.cml" ],
@@ -293,11 +613,20 @@ your binary. Additional arguments can be set in the component manifest:
 This will pass the argument `it_works` to the binary, filtering the tests to
 only those tests that match the pattern. There are many more configuration
 options available in CML including environment variables. More documentation is
-available on the [Fuchsia devsite](https://fuchsia.dev/reference/cml).
+available on the [Fuchsia devsite].
 
 ### Running the compiler test suite
 
 Running the Rust test suite on Fuchsia is [not currently supported], but work is
 underway to enable it.
 
+[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
+[Fuchsia]: https://fuchsia.dev/
+[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
+[rustup]: https://rustup.rs/
+[cargo]: https://doc.rust-lang.org/cargo/
+[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
+[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
+[reference for the file format]: https://fuchsia.dev/reference/cml
+[Fuchsia devsite]: https://fuchsia.dev/reference/cml
 [not currently supported]: https://fxbug.dev/105393
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 1efa67a44b5..e301a793282 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -83,12 +83,13 @@ pre, .rustdoc.source .example-wrap {
 }
 
 .search-results a:hover {
-	background-color: #777;
+	color: #fff !important;
+	background-color: #3c3c3c;
 }
 
 .search-results a:focus {
-	color: #000 !important;
-	background-color: #c6afb3;
+	color: #fff !important;
+	background-color: #3c3c3c;
 }
 .search-results a {
 	color: #0096cf;
diff --git a/src/test/codegen/issue-85872-multiple-reverse.rs b/src/test/codegen/issue-85872-multiple-reverse.rs
new file mode 100644
index 00000000000..591a1aca747
--- /dev/null
+++ b/src/test/codegen/issue-85872-multiple-reverse.rs
@@ -0,0 +1,20 @@
+// min-llvm-version: 15.0.0
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn u16_be_to_arch(mut data: [u8; 2]) -> [u8; 2] {
+    // CHECK-LABEL: @u16_be_to_arch
+    // CHECK: @llvm.bswap.i16
+    data.reverse();
+    data
+}
+
+#[no_mangle]
+pub fn u32_be_to_arch(mut data: [u8; 4]) -> [u8; 4] {
+    // CHECK-LABEL: @u32_be_to_arch
+    // CHECK: @llvm.bswap.i32
+    data.reverse();
+    data
+}
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
index 9a49ae2c6b8..5e328133e62 100644
--- a/src/test/rustdoc-gui/search-result-color.goml
+++ b/src/test/rustdoc-gui/search-result-color.goml
@@ -29,6 +29,23 @@ assert-css: (
     {"color": "rgb(120, 135, 151)"},
 )
 
+// Checking the `<a>` container.
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+
+// Checking color and background on hover.
+move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']"
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']",
+    {"color": "rgb(255, 255, 255)"},
+)
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(255, 255, 255)", "background-color": "rgb(60, 60, 60)"},
+)
+
 // Dark theme
 local-storage: {
     "rustdoc-theme": "dark",
@@ -54,6 +71,23 @@ assert-css: (
     {"color": "rgb(221, 221, 221)"},
 )
 
+// Checking the `<a>` container.
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+
+// Checking color and background on hover.
+move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']"
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']",
+    {"color": "rgb(221, 221, 221)"},
+)
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(221, 221, 221)", "background-color": "rgb(119, 119, 119)"},
+)
+
 // Light theme
 local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
@@ -75,6 +109,23 @@ assert-css: (
     {"color": "rgb(0, 0, 0)"},
 )
 
+// Checking the `<a>` container.
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+
+// Checking color and background on hover.
+move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']"
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']",
+    {"color": "rgb(0, 0, 0)"},
+)
+assert-css: (
+    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    {"color": "rgb(0, 0, 0)", "background-color": "rgb(221, 221, 221)"},
+)
+
 // Check the alias more specifically in the dark theme.
 goto: file://|DOC_PATH|/test_docs/index.html
 // We set the theme so we're sure that the correct values will be used, whatever the computer
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 8a61ea1c924..9f10d92c4e3 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -248,20 +248,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "crossbeam"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
-dependencies = [
- "cfg-if",
- "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-epoch",
- "crossbeam-queue",
- "crossbeam-utils",
-]
-
-[[package]]
 name = "crossbeam-channel"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -297,16 +283,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "crossbeam-queue"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
 name = "crossbeam-utils"
 version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -728,6 +704,7 @@ dependencies = [
  "ide-db",
  "itertools",
  "parser",
+ "stdx",
  "syntax",
  "test-utils",
  "text-edit",
@@ -895,9 +872,9 @@ dependencies = [
 
 [[package]]
 name = "lsp-types"
-version = "0.93.0"
+version = "0.93.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70c74e2173b2b31f8655d33724b4b45ac13f439386f66290f539c22b144c2212"
+checksum = "a3bcfee315dde785ba887edb540b08765fd7df75a7d948844be6bf5712246734"
 dependencies = [
  "bitflags",
  "serde",
@@ -1178,7 +1155,6 @@ dependencies = [
 name = "proc-macro-srv"
 version = "0.0.0"
 dependencies = [
- "crossbeam",
  "expect-test",
  "libloading",
  "mbe",
@@ -1255,6 +1231,26 @@ dependencies = [
 ]
 
 [[package]]
+name = "protobuf"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee4a7d8b91800c8f167a6268d1a1026607368e1adc84e98fe044aeb905302f7"
+dependencies = [
+ "once_cell",
+ "protobuf-support",
+ "thiserror",
+]
+
+[[package]]
+name = "protobuf-support"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ca157fe12fc7ee2e315f2f735e27df41b3d97cdd70ea112824dac1ffb08ee1c"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
 name = "pulldown-cmark"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1385,6 +1381,7 @@ dependencies = [
  "project-model",
  "rayon",
  "rustc-hash",
+ "scip",
  "serde",
  "serde_json",
  "sourcegen",
@@ -1472,6 +1469,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "scip"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2bfbb10286f69fad7c78db71004b7839bf957788359fe0c479f029f9849136b"
+dependencies = [
+ "protobuf",
+]
+
+[[package]]
 name = "scoped-tls"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1657,6 +1663,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
 
 [[package]]
+name = "thiserror"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "thread_local"
 version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1896,6 +1922,7 @@ dependencies = [
  "indexmap",
  "paths",
  "rustc-hash",
+ "stdx",
 ]
 
 [[package]]
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 9580ce8007c..b388e47dee6 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -9,10 +9,11 @@
 use std::{fmt, ops, panic::RefUnwindSafe, str::FromStr, sync::Arc};
 
 use cfg::CfgOptions;
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::FxHashMap;
+use stdx::hash::{NoHashHashMap, NoHashHashSet};
 use syntax::SmolStr;
 use tt::Subtree;
-use vfs::{file_set::FileSet, FileId, VfsPath};
+use vfs::{file_set::FileSet, AnchoredPath, FileId, VfsPath};
 
 /// Files are grouped into source roots. A source root is a directory on the
 /// file systems which is watched for changes. Typically it corresponds to a
@@ -31,22 +32,30 @@ pub struct SourceRoot {
     /// Libraries are considered mostly immutable, this assumption is used to
     /// optimize salsa's query structure
     pub is_library: bool,
-    pub(crate) file_set: FileSet,
+    file_set: FileSet,
 }
 
 impl SourceRoot {
     pub fn new_local(file_set: FileSet) -> SourceRoot {
         SourceRoot { is_library: false, file_set }
     }
+
     pub fn new_library(file_set: FileSet) -> SourceRoot {
         SourceRoot { is_library: true, file_set }
     }
+
     pub fn path_for_file(&self, file: &FileId) -> Option<&VfsPath> {
         self.file_set.path_for_file(file)
     }
+
     pub fn file_for_path(&self, path: &VfsPath) -> Option<&FileId> {
         self.file_set.file_for_path(path)
     }
+
+    pub fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
+        self.file_set.resolve_path(path)
+    }
+
     pub fn iter(&self) -> impl Iterator<Item = FileId> + '_ {
         self.file_set.iter()
     }
@@ -72,12 +81,19 @@ impl SourceRoot {
 /// <https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/architecture.md#serialization>
 #[derive(Debug, Clone, Default /* Serialize, Deserialize */)]
 pub struct CrateGraph {
-    arena: FxHashMap<CrateId, CrateData>,
+    arena: NoHashHashMap<CrateId, CrateData>,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct CrateId(pub u32);
 
+impl stdx::hash::NoHashHashable for CrateId {}
+impl std::hash::Hash for CrateId {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateName(SmolStr);
 
@@ -342,7 +358,7 @@ impl CrateGraph {
         // Check if adding a dep from `from` to `to` creates a cycle. To figure
         // that out, look for a  path in the *opposite* direction, from `to` to
         // `from`.
-        if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) {
+        if let Some(path) = self.find_path(&mut NoHashHashSet::default(), dep.crate_id, from) {
             let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect();
             let err = CyclicDependenciesError { path };
             assert!(err.from().0 == from && err.to().0 == dep.crate_id);
@@ -365,7 +381,7 @@ impl CrateGraph {
     /// including the crate itself.
     pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
         let mut worklist = vec![of];
-        let mut deps = FxHashSet::default();
+        let mut deps = NoHashHashSet::default();
 
         while let Some(krate) = worklist.pop() {
             if !deps.insert(krate) {
@@ -382,10 +398,10 @@ impl CrateGraph {
     /// including the crate itself.
     pub fn transitive_rev_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
         let mut worklist = vec![of];
-        let mut rev_deps = FxHashSet::default();
+        let mut rev_deps = NoHashHashSet::default();
         rev_deps.insert(of);
 
-        let mut inverted_graph = FxHashMap::<_, Vec<_>>::default();
+        let mut inverted_graph = NoHashHashMap::<_, Vec<_>>::default();
         self.arena.iter().for_each(|(&krate, data)| {
             data.dependencies
                 .iter()
@@ -409,7 +425,7 @@ impl CrateGraph {
     /// come before the crate itself).
     pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
         let mut res = Vec::new();
-        let mut visited = FxHashSet::default();
+        let mut visited = NoHashHashSet::default();
 
         for krate in self.arena.keys().copied() {
             go(self, &mut visited, &mut res, krate);
@@ -419,7 +435,7 @@ impl CrateGraph {
 
         fn go(
             graph: &CrateGraph,
-            visited: &mut FxHashSet<CrateId>,
+            visited: &mut NoHashHashSet<CrateId>,
             res: &mut Vec<CrateId>,
             source: CrateId,
         ) {
@@ -459,7 +475,7 @@ impl CrateGraph {
 
     fn find_path(
         &self,
-        visited: &mut FxHashSet<CrateId>,
+        visited: &mut NoHashHashSet<CrateId>,
         from: CrateId,
         to: CrateId,
     ) -> Option<Vec<CrateId>> {
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 2d0a95b09d9..da11e4ae7bb 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -8,7 +8,7 @@ pub mod fixture;
 
 use std::{panic, sync::Arc};
 
-use rustc_hash::FxHashSet;
+use stdx::hash::NoHashHashSet;
 use syntax::{ast, Parse, SourceFile, TextRange, TextSize};
 
 pub use crate::{
@@ -58,7 +58,7 @@ pub trait FileLoader {
     /// Text of the file.
     fn file_text(&self, file_id: FileId) -> Arc<String>;
     fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
-    fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>;
+    fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>>;
 }
 
 /// Database which stores all significant input facts: source code and project
@@ -94,10 +94,10 @@ pub trait SourceDatabaseExt: SourceDatabase {
     #[salsa::input]
     fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
 
-    fn source_root_crates(&self, id: SourceRootId) -> Arc<FxHashSet<CrateId>>;
+    fn source_root_crates(&self, id: SourceRootId) -> Arc<NoHashHashSet<CrateId>>;
 }
 
-fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<FxHashSet<CrateId>> {
+fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<NoHashHashSet<CrateId>> {
     let graph = db.crate_graph();
     let res = graph
         .iter()
@@ -120,10 +120,10 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
         // FIXME: this *somehow* should be platform agnostic...
         let source_root = self.0.file_source_root(path.anchor);
         let source_root = self.0.source_root(source_root);
-        source_root.file_set.resolve_path(path)
+        source_root.resolve_path(path)
     }
 
-    fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
+    fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
         let _p = profile::span("relevant_crates");
         let source_root = self.0.file_source_root(file_id);
         self.0.source_root_crates(source_root)
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index c22945c81fc..d9f4ef5b7ff 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -125,6 +125,7 @@ pub enum Progress {
     DidCheckCrate(String),
     DidFinish(io::Result<()>),
     DidCancel,
+    DidFailToRestart(String),
 }
 
 enum Restart {
@@ -193,10 +194,11 @@ impl FlycheckActor {
                             self.progress(Progress::DidStart);
                         }
                         Err(error) => {
-                            tracing::error!(
-                                command = ?self.check_command(),
-                                %error, "failed to restart flycheck"
-                            );
+                            self.progress(Progress::DidFailToRestart(format!(
+                                "Failed to run the following command: {:?} error={}",
+                                self.check_command(),
+                                error
+                            )));
                         }
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 35c8708955a..631ae3cf11f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -2,7 +2,7 @@
 
 use std::sync::Arc;
 
-use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind};
+use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
 use smallvec::SmallVec;
 use syntax::ast;
 
@@ -12,7 +12,10 @@ use crate::{
     db::DefDatabase,
     intern::Interned,
     item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
-    nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap},
+    nameres::{
+        attr_resolution::ResolvedAttr, diagnostics::DefDiagnostic, proc_macro::ProcMacroKind,
+        DefMap,
+    },
     type_ref::{TraitRef, TypeBound, TypeRef},
     visibility::RawVisibility,
     AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -210,6 +213,13 @@ pub struct TraitData {
 
 impl TraitData {
     pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
+        db.trait_data_with_diagnostics(tr).0
+    }
+
+    pub(crate) fn trait_data_with_diagnostics_query(
+        db: &dyn DefDatabase,
+        tr: TraitId,
+    ) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
         let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
         let item_tree = tree_id.item_tree(db);
         let tr_def = &item_tree[tree_id.value];
@@ -229,17 +239,20 @@ impl TraitData {
         let mut collector =
             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
         collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
-        let (items, attribute_calls) = collector.finish();
-
-        Arc::new(TraitData {
-            name,
-            attribute_calls,
-            items,
-            is_auto,
-            is_unsafe,
-            visibility,
-            skip_array_during_method_dispatch,
-        })
+        let (items, attribute_calls, diagnostics) = collector.finish();
+
+        (
+            Arc::new(TraitData {
+                name,
+                attribute_calls,
+                items,
+                is_auto,
+                is_unsafe,
+                visibility,
+                skip_array_during_method_dispatch,
+            }),
+            Arc::new(diagnostics),
+        )
     }
 
     pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
@@ -280,7 +293,14 @@ pub struct ImplData {
 
 impl ImplData {
     pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
-        let _p = profile::span("impl_data_query");
+        db.impl_data_with_diagnostics(id).0
+    }
+
+    pub(crate) fn impl_data_with_diagnostics_query(
+        db: &dyn DefDatabase,
+        id: ImplId,
+    ) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
+        let _p = profile::span("impl_data_with_diagnostics_query");
         let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
 
         let item_tree = tree_id.item_tree(db);
@@ -293,10 +313,13 @@ impl ImplData {
             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
         collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
 
-        let (items, attribute_calls) = collector.finish();
+        let (items, attribute_calls, diagnostics) = collector.finish();
         let items = items.into_iter().map(|(_, item)| item).collect();
 
-        Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls })
+        (
+            Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
+            Arc::new(diagnostics),
+        )
     }
 
     pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
@@ -437,6 +460,7 @@ struct AssocItemCollector<'a> {
     db: &'a dyn DefDatabase,
     module_id: ModuleId,
     def_map: Arc<DefMap>,
+    inactive_diagnostics: Vec<DefDiagnostic>,
     container: ItemContainerId,
     expander: Expander,
 
@@ -459,15 +483,21 @@ impl<'a> AssocItemCollector<'a> {
             expander: Expander::new(db, file_id, module_id),
             items: Vec::new(),
             attr_calls: Vec::new(),
+            inactive_diagnostics: Vec::new(),
         }
     }
 
     fn finish(
         self,
-    ) -> (Vec<(Name, AssocItemId)>, Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>) {
+    ) -> (
+        Vec<(Name, AssocItemId)>,
+        Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
+        Vec<DefDiagnostic>,
+    ) {
         (
             self.items,
             if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
+            self.inactive_diagnostics,
         )
     }
 
@@ -479,6 +509,12 @@ impl<'a> AssocItemCollector<'a> {
         'items: for &item in assoc_items {
             let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
             if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
+                self.inactive_diagnostics.push(DefDiagnostic::unconfigured_code(
+                    self.module_id.local_id,
+                    InFile::new(self.expander.current_file_id(), item.ast_id(&item_tree).upcast()),
+                    attrs.cfg().unwrap(),
+                    self.expander.cfg_options().clone(),
+                ));
                 continue;
             }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index df6dcb024b5..40b2f734b71 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -20,7 +20,7 @@ use crate::{
     intern::Interned,
     item_tree::{AttrOwner, ItemTree},
     lang_item::{LangItemTarget, LangItems},
-    nameres::DefMap,
+    nameres::{diagnostics::DefDiagnostic, DefMap},
     visibility::{self, Visibility},
     AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
     ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
@@ -106,9 +106,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
     #[salsa::invoke(ImplData::impl_data_query)]
     fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
 
+    #[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
+    fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);
+
     #[salsa::invoke(TraitData::trait_data_query)]
     fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
 
+    #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
+    fn trait_data_with_diagnostics(&self, tr: TraitId)
+        -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);
+
     #[salsa::invoke(TypeAliasData::type_alias_data_query)]
     fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index 0d01f6d0aba..ed7e920fd2b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -73,7 +73,7 @@ impl DefDiagnostic {
         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
     }
 
-    pub(super) fn unconfigured_code(
+    pub fn unconfigured_code(
         container: LocalModuleId,
         ast: AstId<ast::Item>,
         cfg: CfgExpr,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index 9cdc18d6b66..b7908bddaa1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -10,7 +10,7 @@ use base_db::{
     SourceDatabase, Upcast,
 };
 use hir_expand::{db::AstDatabase, InFile};
-use rustc_hash::FxHashSet;
+use stdx::hash::NoHashHashSet;
 use syntax::{algo, ast, AstNode};
 
 use crate::{
@@ -76,7 +76,7 @@ impl FileLoader for TestDB {
     fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
         FileLoaderDelegate(self).resolve_path(path)
     }
-    fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
+    fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
         FileLoaderDelegate(self).relevant_crates(file_id)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index ae115c8c0da..3f6d0844e9c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -6,7 +6,7 @@
 //!
 //! This usually involves resolving names, collecting generic arguments etc.
 use std::{
-    cell::{Cell, RefCell},
+    cell::{Cell, RefCell, RefMut},
     iter,
     sync::Arc,
 };
@@ -330,26 +330,26 @@ impl<'a> TyLoweringContext<'a> {
                 }
             }
             TypeRef::Macro(macro_call) => {
-                let (expander, recursion_start) = {
-                    let mut expander = self.expander.borrow_mut();
-                    if expander.is_some() {
-                        (Some(expander), false)
-                    } else {
-                        *expander = Some(Expander::new(
-                            self.db.upcast(),
-                            macro_call.file_id,
-                            self.resolver.module(),
-                        ));
-                        (Some(expander), true)
+                let (mut expander, recursion_start) = {
+                    match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
+                        Ok(expander) => (expander, false),
+                        Err(expander) => (
+                            RefMut::map(expander, |it| {
+                                it.insert(Expander::new(
+                                    self.db.upcast(),
+                                    macro_call.file_id,
+                                    self.resolver.module(),
+                                ))
+                            }),
+                            true,
+                        ),
                     }
                 };
-                let ty = if let Some(mut expander) = expander {
-                    let expander_mut = expander.as_mut().unwrap();
+                let ty = {
                     let macro_call = macro_call.to_node(self.db.upcast());
-                    match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
+                    match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
                         Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
-                            let ctx =
-                                LowerCtx::new(self.db.upcast(), expander_mut.current_file_id());
+                            let ctx = LowerCtx::new(self.db.upcast(), expander.current_file_id());
                             let type_ref = TypeRef::from_ast(&ctx, expanded);
 
                             drop(expander);
@@ -364,8 +364,6 @@ impl<'a> TyLoweringContext<'a> {
                         }
                         _ => None,
                     }
-                } else {
-                    None
                 };
                 if recursion_start {
                     *self.expander.borrow_mut() = None;
@@ -479,7 +477,14 @@ impl<'a> TyLoweringContext<'a> {
                         TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
                     }
                     ParamLoweringMode::Variable => {
-                        let idx = generics.param_idx(param_id.into()).expect("matching generics");
+                        let idx = match generics.param_idx(param_id.into()) {
+                            None => {
+                                never!("no matching generics");
+                                return (TyKind::Error.intern(Interner), None);
+                            }
+                            Some(idx) => idx,
+                        };
+
                         TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
index dc7252f7072..118e5311e9a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
@@ -10,7 +10,7 @@ use base_db::{
 };
 use hir_def::{db::DefDatabase, ModuleId};
 use hir_expand::db::AstDatabase;
-use rustc_hash::{FxHashMap, FxHashSet};
+use stdx::hash::{NoHashHashMap, NoHashHashSet};
 use syntax::TextRange;
 use test_utils::extract_annotations;
 
@@ -80,7 +80,7 @@ impl FileLoader for TestDB {
     fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
         FileLoaderDelegate(self).resolve_path(path)
     }
-    fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
+    fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
         FileLoaderDelegate(self).relevant_crates(file_id)
     }
 }
@@ -102,7 +102,7 @@ impl TestDB {
         self.module_for_file_opt(file_id).unwrap()
     }
 
-    pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
+    pub(crate) fn extract_annotations(&self) -> NoHashHashMap<FileId, Vec<(TextRange, String)>> {
         let mut files = Vec::new();
         let crate_graph = self.crate_graph();
         for krate in crate_graph.iter() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index 1b5ed0603bf..c7895db1afb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -1527,6 +1527,34 @@ unsafe impl Storage for InlineStorage {
 }
 
 #[test]
+fn gat_crash_3() {
+    // FIXME: This test currently crashes rust analyzer in a debug build but not in a
+    // release build (i.e. for the user). With the assumption that tests will always be run
+    // in debug mode, we catch the unwind and expect that it panicked. See the
+    // [`crate::utils::generics`] function for more information.
+    cov_mark::check!(ignore_gats);
+    std::panic::catch_unwind(|| {
+        check_no_mismatches(
+            r#"
+trait Collection {
+    type Item;
+    type Member<T>: Collection<Item = T>;
+    fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>;
+}
+struct ConstGen<T, const N: usize> {
+    data: [T; N],
+}
+impl<T, const N: usize> Collection for ConstGen<T, N> {
+    type Item = T;
+    type Member<U> = ConstGen<U, N>;
+}
+        "#,
+        );
+    })
+    .expect_err("must panic");
+}
+
+#[test]
 fn cfgd_out_self_param() {
     cov_mark::check!(cfgd_out_self_param);
     check_no_mismatches(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 83319755da7..d6638db0285 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -176,10 +176,19 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
     let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
     if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
         let params = db.generic_params(def);
+        let parent_params = &parent_generics.as_ref().unwrap().params;
         let has_consts =
             params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
-        return if has_consts {
-            // XXX: treat const generic associated types as not existing to avoid crashes (#11769)
+        let parent_has_consts =
+            parent_params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
+        return if has_consts || parent_has_consts {
+            // XXX: treat const generic associated types as not existing to avoid crashes
+            // (#11769)
+            //
+            // Note: Also crashes when the parent has const generics (also even if the GAT
+            // doesn't use them), see `tests::regression::gat_crash_3` for an example.
+            // Avoids that by disabling GATs when the parent (i.e. `impl` block) has
+            // const generics (#12193).
             //
             // Chalk expects the inner associated type's parameters to come
             // *before*, not after the trait's generics as we've always done it.
@@ -264,12 +273,8 @@ impl Generics {
 
     fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstParamData)> {
         if param.parent == self.def {
-            let (idx, (_local_id, data)) = self
-                .params
-                .iter()
-                .enumerate()
-                .find(|(_, (idx, _))| *idx == param.local_id)
-                .unwrap();
+            let (idx, (_local_id, data)) =
+                self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?;
             let parent_len = self.parent_generics().map_or(0, Generics::len);
             Some((parent_len + idx, data))
         } else {
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index aa019ca4838..6dccf2ed20b 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -511,6 +511,7 @@ impl Module {
             .collect()
     }
 
+    /// Fills `acc` with the module's diagnostics.
     pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
         let _p = profile::span("Module::diagnostics").detail(|| {
             format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
@@ -531,11 +532,21 @@ impl Module {
                         m.diagnostics(db, acc)
                     }
                 }
+                ModuleDef::Trait(t) => {
+                    for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
+                        emit_def_diagnostic(db, acc, diag);
+                    }
+                    acc.extend(decl.diagnostics(db))
+                }
                 _ => acc.extend(decl.diagnostics(db)),
             }
         }
 
         for impl_def in self.impl_defs(db) {
+            for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
+                emit_def_diagnostic(db, acc, diag);
+            }
+
             for item in impl_def.items(db) {
                 let def: DefWithBody = match item {
                     AssocItem::Function(it) => it.into(),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
index af584cdb438..03aa8601d14 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
@@ -171,6 +171,25 @@ fn collect_used_generics<'gp>(
         ast::Type::RefType(ref_) => generics.extend(
             ref_.lifetime().and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
         ),
+        ast::Type::ArrayType(ar) => {
+            if let Some(expr) = ar.expr() {
+                if let ast::Expr::PathExpr(p) = expr {
+                    if let Some(path) = p.path() {
+                        if let Some(name_ref) = path.as_single_name_ref() {
+                            if let Some(param) = known_generics.iter().find(|gp| {
+                                if let ast::GenericParam::ConstParam(cp) = gp {
+                                    cp.name().map_or(false, |n| n.text() == name_ref.text())
+                                } else {
+                                    false
+                                }
+                            }) {
+                                generics.push(param);
+                            }
+                        }
+                    }
+                }
+            }
+        }
         _ => (),
     });
     // stable resort to lifetime, type, const
@@ -357,4 +376,29 @@ impl<'outer, Outer, const OUTER: usize> () {
 "#,
         );
     }
+
+    #[test]
+    fn issue_11197() {
+        check_assist(
+            extract_type_alias,
+            r#"
+struct Foo<T, const N: usize>
+where
+    [T; N]: Sized,
+{
+    arr: $0[T; N]$0,
+}
+            "#,
+            r#"
+type $0Type<T, const N: usize> = [T; N];
+
+struct Foo<T, const N: usize>
+where
+    [T; N]: Sized,
+{
+    arr: Type<T, N>,
+}
+            "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
index b5d092e39b0..96890ad51a6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
@@ -311,12 +311,16 @@ fn inline(
     } else {
         fn_body.clone_for_update()
     };
-    if let Some(t) = body.syntax().ancestors().find_map(ast::Impl::cast).and_then(|i| i.self_ty()) {
-        body.syntax()
-            .descendants_with_tokens()
-            .filter_map(NodeOrToken::into_token)
-            .filter(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
-            .for_each(|tok| ted::replace(tok, t.syntax()));
+    if let Some(imp) = body.syntax().ancestors().find_map(ast::Impl::cast) {
+        if !node.syntax().ancestors().any(|anc| &anc == imp.syntax()) {
+            if let Some(t) = imp.self_ty() {
+                body.syntax()
+                    .descendants_with_tokens()
+                    .filter_map(NodeOrToken::into_token)
+                    .filter(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
+                    .for_each(|tok| ted::replace(tok, t.syntax()));
+            }
+        }
     }
     let usages_for_locals = |local| {
         Definition::Local(local)
@@ -1224,4 +1228,29 @@ fn main() {
 "#,
         )
     }
+
+    #[test]
+    fn inline_call_with_self_type_but_within_same_impl() {
+        check_assist(
+            inline_call,
+            r#"
+struct A(u32);
+impl A {
+    fn f() -> Self { Self(1919810) }
+    fn main() {
+        Self::f$0();
+    }
+}
+"#,
+            r#"
+struct A(u32);
+impl A {
+    fn f() -> Self { Self(1919810) }
+    fn main() {
+        Self(1919810);
+    }
+}
+"#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 759742d3472..a5e854b74df 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -64,8 +64,11 @@ pub(crate) struct PathCompletionCtx {
     pub(super) qualified: Qualified,
     /// The parent of the path we are completing.
     pub(super) parent: Option<ast::Path>,
+    #[allow(dead_code)]
     /// The path of which we are completing the segment
     pub(super) path: ast::Path,
+    /// The path of which we are completing the segment in the original file
+    pub(crate) original_path: Option<ast::Path>,
     pub(super) kind: PathKind,
     /// Whether the path segment has type args or not.
     pub(super) has_type_args: bool,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 22ec7cead49..01dd9a234f5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -588,12 +588,15 @@ impl<'a> CompletionContext<'a> {
         };
 
         let path = segment.parent_path();
+        let original_path = find_node_in_file_compensated(sema, original_file, &path);
+
         let mut path_ctx = PathCompletionCtx {
             has_call_parens: false,
             has_macro_bang: false,
             qualified: Qualified::No,
             parent: None,
             path: path.clone(),
+            original_path,
             kind: PathKind::Item { kind: ItemListKind::SourceFile },
             has_type_args: false,
             use_tree_parent: false,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index a2cf6d68e5b..86302cb0678 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -323,9 +323,7 @@ fn render_resolution_path(
             ..CompletionRelevance::default()
         });
 
-        if let Some(ref_match) = compute_ref_match(completion, &ty) {
-            item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-        }
+        path_ref_match(completion, path_ctx, &ty, &mut item);
     };
     item
 }
@@ -453,6 +451,29 @@ fn compute_ref_match(
     None
 }
 
+fn path_ref_match(
+    completion: &CompletionContext<'_>,
+    path_ctx: &PathCompletionCtx,
+    ty: &hir::Type,
+    item: &mut Builder,
+) {
+    if let Some(original_path) = &path_ctx.original_path {
+        // At least one char was typed by the user already, in that case look for the original path
+        if let Some(original_path) = completion.sema.original_ast_node(original_path.clone()) {
+            if let Some(ref_match) = compute_ref_match(completion, ty) {
+                item.ref_match(ref_match, original_path.syntax().text_range().start());
+            }
+        }
+    } else {
+        // completion requested on an empty identifier, there is no path here yet.
+        // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
+        // as long as nothing was typed yet
+        if let Some(ref_match) = compute_ref_match(completion, ty) {
+            item.ref_match(ref_match, completion.position.offset);
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use std::cmp;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
index 9cf64691298..37612084604 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
@@ -79,18 +79,18 @@ fn render(
         ..ctx.completion_relevance()
     });
 
-    if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
-        match func_kind {
-            FuncKind::Function(path_ctx) => {
-                item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-            }
-            FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
-                if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
+    match func_kind {
+        FuncKind::Function(path_ctx) => {
+            super::path_ref_match(completion, path_ctx, &ret_type, &mut item);
+        }
+        FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
+            if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
+                if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
                     item.ref_match(ref_match, original_expr.syntax().text_range().start());
                 }
             }
-            _ => (),
         }
+        _ => (),
     }
 
     item.set_documentation(ctx.docs(func))
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
index af9c88a7e0a..0c791ac570c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
@@ -2,13 +2,12 @@
 
 use hir::{db::HirDatabase, Documentation, HasAttrs, StructKind};
 use ide_db::SymbolKind;
-use syntax::AstNode;
 
 use crate::{
     context::{CompletionContext, PathCompletionCtx, PathKind},
     item::{Builder, CompletionItem},
     render::{
-        compute_ref_match, compute_type_match,
+        compute_type_match,
         variant::{
             format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit,
             visible_fields, RenderedLiteral,
@@ -125,9 +124,8 @@ fn render(
         type_match: compute_type_match(ctx.completion, &ty),
         ..ctx.completion_relevance()
     });
-    if let Some(ref_match) = compute_ref_match(completion, &ty) {
-        item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-    }
+
+    super::path_ref_match(completion, path_ctx, &ty, &mut item);
 
     if let Some(import_to_add) = ctx.import_to_add {
         item.add_import(import_to_add);
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index 966bba616f6..1ec62a8425a 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -52,6 +52,7 @@ use hir::{
     db::{AstDatabase, DefDatabase, HirDatabase},
     symbols::FileSymbolKind,
 };
+use stdx::hash::NoHashHashSet;
 
 use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
 pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
@@ -118,7 +119,7 @@ impl FileLoader for RootDatabase {
     fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
         FileLoaderDelegate(self).resolve_path(path)
     }
-    fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
+    fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
         FileLoaderDelegate(self).relevant_crates(file_id)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
index 68ad07ee83f..75d49ff2fd7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
@@ -2,7 +2,7 @@
 //! representation.
 use std::{iter, mem};
 
-use rustc_hash::FxHashMap;
+use stdx::hash::NoHashHashMap;
 use syntax::{TextRange, TextSize};
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -10,7 +10,7 @@ pub struct LineIndex {
     /// Offset the the beginning of each line, zero-based
     pub(crate) newlines: Vec<TextSize>,
     /// List of non-ASCII characters on each line
-    pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>,
+    pub(crate) utf16_lines: NoHashHashMap<u32, Vec<Utf16Char>>,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -55,7 +55,7 @@ impl Utf16Char {
 
 impl LineIndex {
     pub fn new(text: &str) -> LineIndex {
-        let mut utf16_lines = FxHashMap::default();
+        let mut utf16_lines = NoHashHashMap::default();
         let mut utf16_chars = Vec::new();
 
         let mut newlines = vec![0.into()];
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index 2f4aa113170..7deffe8e0f6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -9,7 +9,7 @@ use std::{mem, sync::Arc};
 use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
 use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
 use once_cell::unsync::Lazy;
-use rustc_hash::FxHashMap;
+use stdx::hash::NoHashHashMap;
 use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
 
 use crate::{
@@ -20,7 +20,7 @@ use crate::{
 
 #[derive(Debug, Default, Clone)]
 pub struct UsageSearchResult {
-    pub references: FxHashMap<FileId, Vec<FileReference>>,
+    pub references: NoHashHashMap<FileId, Vec<FileReference>>,
 }
 
 impl UsageSearchResult {
@@ -45,7 +45,7 @@ impl UsageSearchResult {
 
 impl IntoIterator for UsageSearchResult {
     type Item = (FileId, Vec<FileReference>);
-    type IntoIter = <FxHashMap<FileId, Vec<FileReference>> as IntoIterator>::IntoIter;
+    type IntoIter = <NoHashHashMap<FileId, Vec<FileReference>> as IntoIterator>::IntoIter;
 
     fn into_iter(self) -> Self::IntoIter {
         self.references.into_iter()
@@ -78,17 +78,17 @@ pub enum ReferenceCategory {
 /// e.g. for things like local variables.
 #[derive(Clone, Debug)]
 pub struct SearchScope {
-    entries: FxHashMap<FileId, Option<TextRange>>,
+    entries: NoHashHashMap<FileId, Option<TextRange>>,
 }
 
 impl SearchScope {
-    fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope {
+    fn new(entries: NoHashHashMap<FileId, Option<TextRange>>) -> SearchScope {
         SearchScope { entries }
     }
 
     /// Build a search scope spanning the entire crate graph of files.
     fn crate_graph(db: &RootDatabase) -> SearchScope {
-        let mut entries = FxHashMap::default();
+        let mut entries = NoHashHashMap::default();
 
         let graph = db.crate_graph();
         for krate in graph.iter() {
@@ -102,7 +102,7 @@ impl SearchScope {
 
     /// Build a search scope spanning all the reverse dependencies of the given crate.
     fn reverse_dependencies(db: &RootDatabase, of: hir::Crate) -> SearchScope {
-        let mut entries = FxHashMap::default();
+        let mut entries = NoHashHashMap::default();
         for rev_dep in of.transitive_reverse_dependencies(db) {
             let root_file = rev_dep.root_file(db);
             let source_root_id = db.file_source_root(root_file);
@@ -117,14 +117,12 @@ impl SearchScope {
         let root_file = of.root_file(db);
         let source_root_id = db.file_source_root(root_file);
         let source_root = db.source_root(source_root_id);
-        SearchScope {
-            entries: source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>(),
-        }
+        SearchScope { entries: source_root.iter().map(|id| (id, None)).collect() }
     }
 
     /// Build a search scope spanning the given module and all its submodules.
     fn module_and_children(db: &RootDatabase, module: hir::Module) -> SearchScope {
-        let mut entries = FxHashMap::default();
+        let mut entries = NoHashHashMap::default();
 
         let (file_id, range) = {
             let InFile { file_id, value } = module.definition_source(db);
@@ -157,7 +155,7 @@ impl SearchScope {
 
     /// Build an empty search scope.
     pub fn empty() -> SearchScope {
-        SearchScope::new(FxHashMap::default())
+        SearchScope::new(NoHashHashMap::default())
     }
 
     /// Build a empty search scope spanning the given file.
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
index 21314ad74ef..8e338061df4 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
@@ -6,8 +6,7 @@
 use std::{collections::hash_map::Entry, iter, mem};
 
 use base_db::{AnchoredPathBuf, FileId};
-use rustc_hash::FxHashMap;
-use stdx::never;
+use stdx::{hash::NoHashHashMap, never};
 use syntax::{algo, AstNode, SyntaxNode, SyntaxNodePtr, TextRange, TextSize};
 use text_edit::{TextEdit, TextEditBuilder};
 
@@ -15,7 +14,7 @@ use crate::SnippetCap;
 
 #[derive(Default, Debug, Clone)]
 pub struct SourceChange {
-    pub source_file_edits: FxHashMap<FileId, TextEdit>,
+    pub source_file_edits: NoHashHashMap<FileId, TextEdit>,
     pub file_system_edits: Vec<FileSystemEdit>,
     pub is_snippet: bool,
 }
@@ -24,7 +23,7 @@ impl SourceChange {
     /// Creates a new SourceChange with the given label
     /// from the edits.
     pub fn from_edits(
-        source_file_edits: FxHashMap<FileId, TextEdit>,
+        source_file_edits: NoHashHashMap<FileId, TextEdit>,
         file_system_edits: Vec<FileSystemEdit>,
     ) -> Self {
         SourceChange { source_file_edits, file_system_edits, is_snippet: false }
@@ -78,8 +77,8 @@ impl Extend<FileSystemEdit> for SourceChange {
     }
 }
 
-impl From<FxHashMap<FileId, TextEdit>> for SourceChange {
-    fn from(source_file_edits: FxHashMap<FileId, TextEdit>) -> SourceChange {
+impl From<NoHashHashMap<FileId, TextEdit>> for SourceChange {
+    fn from(source_file_edits: NoHashHashMap<FileId, TextEdit>) -> SourceChange {
         SourceChange { source_file_edits, file_system_edits: Vec::new(), is_snippet: false }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
index 5694f33525e..04918891b25 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
@@ -106,18 +106,17 @@ fn f() {
 
     #[test]
     fn inactive_assoc_item() {
-        // FIXME these currently don't work, hence the *
         check(
             r#"
 struct Foo;
 impl Foo {
     #[cfg(any())] pub fn f() {}
-  //*************************** weak: code is inactive due to #[cfg] directives
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
 }
 
 trait Bar {
     #[cfg(any())] pub fn f() {}
-  //*************************** weak: code is inactive due to #[cfg] directives
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index d36dd02d45c..73314e0f330 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -20,6 +20,7 @@ parser = { path = "../parser", version = "0.0.0" }
 syntax = { path = "../syntax", version = "0.0.0" }
 ide-db = { path = "../ide-db", version = "0.0.0" }
 hir = { path = "../hir", version = "0.0.0" }
+stdx = { path = "../stdx", version = "0.0.0" }
 
 [dev-dependencies]
 test-utils = { path = "../test-utils" }
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
index 739e0ccb436..d9834ee63ad 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
@@ -86,11 +86,9 @@ pub use crate::{errors::SsrError, from_comment::ssr_from_comment, matching::Matc
 
 use crate::{errors::bail, matching::MatchFailureReason};
 use hir::Semantics;
-use ide_db::{
-    base_db::{FileId, FilePosition, FileRange},
-    FxHashMap,
-};
+use ide_db::base_db::{FileId, FilePosition, FileRange};
 use resolving::ResolvedRule;
+use stdx::hash::NoHashHashMap;
 use syntax::{ast, AstNode, SyntaxNode, TextRange};
 use text_edit::TextEdit;
 
@@ -170,9 +168,9 @@ impl<'db> MatchFinder<'db> {
     }
 
     /// Finds matches for all added rules and returns edits for all found matches.
-    pub fn edits(&self) -> FxHashMap<FileId, TextEdit> {
+    pub fn edits(&self) -> NoHashHashMap<FileId, TextEdit> {
         use ide_db::base_db::SourceDatabaseExt;
-        let mut matches_by_file = FxHashMap::default();
+        let mut matches_by_file = NoHashHashMap::default();
         for m in self.matches().matches {
             matches_by_file
                 .entry(m.range.file_id)
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index 582e9fe7e80..92ce26b422e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -184,10 +184,10 @@ pub(crate) fn resolve_doc_path_for_def(
         Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
         Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
         Definition::Field(it) => it.resolve_doc_path(db, link, ns),
+        Definition::SelfType(it) => it.resolve_doc_path(db, link, ns),
         Definition::BuiltinAttr(_)
         | Definition::ToolModule(_)
         | Definition::BuiltinType(_)
-        | Definition::SelfType(_)
         | Definition::Local(_)
         | Definition::GenericParam(_)
         | Definition::Label(_)
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index dd108fa7999..d61d69a090b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -87,7 +87,7 @@ pub use crate::{
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
-    moniker::{MonikerKind, MonikerResult, PackageInformation},
+    moniker::{MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation},
     move_item::Direction,
     navigation_target::NavigationTarget,
     prime_caches::ParallelPrimeCachesProgress,
@@ -98,7 +98,7 @@ pub use crate::{
     static_index::{StaticIndex, StaticIndexedFile, TokenId, TokenStaticData},
     syntax_highlighting::{
         tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag},
-        HlRange,
+        HighlightConfig, HlRange,
     },
 };
 pub use hir::{Documentation, Semantics};
@@ -517,8 +517,12 @@ impl Analysis {
     }
 
     /// Computes syntax highlighting for the given file
-    pub fn highlight(&self, file_id: FileId) -> Cancellable<Vec<HlRange>> {
-        self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false))
+    pub fn highlight(
+        &self,
+        highlight_config: HighlightConfig,
+        file_id: FileId,
+    ) -> Cancellable<Vec<HlRange>> {
+        self.with_db(|db| syntax_highlighting::highlight(db, highlight_config, file_id, None))
     }
 
     /// Computes all ranges to highlight for a given item in a file.
@@ -533,9 +537,13 @@ impl Analysis {
     }
 
     /// Computes syntax highlighting for the given file range.
-    pub fn highlight_range(&self, frange: FileRange) -> Cancellable<Vec<HlRange>> {
+    pub fn highlight_range(
+        &self,
+        highlight_config: HighlightConfig,
+        frange: FileRange,
+    ) -> Cancellable<Vec<HlRange>> {
         self.with_db(|db| {
-            syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false)
+            syntax_highlighting::highlight(db, highlight_config, frange.file_id, Some(frange.range))
         })
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 4f758967b46..600a526300c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -14,16 +14,38 @@ use syntax::{AstNode, SyntaxKind::*, T};
 use crate::{doc_links::token_as_doc_comment, RangeInfo};
 
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum MonikerDescriptorKind {
+    Namespace,
+    Type,
+    Term,
+    Method,
+    TypeParameter,
+    Parameter,
+    Macro,
+    Meta,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct MonikerDescriptor {
+    pub name: Name,
+    pub desc: MonikerDescriptorKind,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct MonikerIdentifier {
-    crate_name: String,
-    path: Vec<Name>,
+    pub crate_name: String,
+    pub description: Vec<MonikerDescriptor>,
 }
 
 impl ToString for MonikerIdentifier {
     fn to_string(&self) -> String {
         match self {
-            MonikerIdentifier { path, crate_name } => {
-                format!("{}::{}", crate_name, path.iter().map(|x| x.to_string()).join("::"))
+            MonikerIdentifier { description, crate_name } => {
+                format!(
+                    "{}::{}",
+                    crate_name,
+                    description.iter().map(|x| x.name.to_string()).join("::")
+                )
             }
         }
     }
@@ -42,6 +64,12 @@ pub struct MonikerResult {
     pub package_information: PackageInformation,
 }
 
+impl MonikerResult {
+    pub fn from_def(db: &RootDatabase, def: Definition, from_crate: Crate) -> Option<Self> {
+        def_to_moniker(db, def, from_crate)
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct PackageInformation {
     pub name: String,
@@ -105,13 +133,23 @@ pub(crate) fn def_to_moniker(
     def: Definition,
     from_crate: Crate,
 ) -> Option<MonikerResult> {
-    if matches!(def, Definition::GenericParam(_) | Definition::SelfType(_) | Definition::Local(_)) {
+    if matches!(
+        def,
+        Definition::GenericParam(_)
+            | Definition::Label(_)
+            | Definition::DeriveHelper(_)
+            | Definition::BuiltinAttr(_)
+            | Definition::ToolModule(_)
+    ) {
         return None;
     }
+
     let module = def.module(db)?;
     let krate = module.krate();
-    let mut path = vec![];
-    path.extend(module.path_to_root(db).into_iter().filter_map(|x| x.name(db)));
+    let mut description = vec![];
+    description.extend(module.path_to_root(db).into_iter().filter_map(|x| {
+        Some(MonikerDescriptor { name: x.name(db)?, desc: MonikerDescriptorKind::Namespace })
+    }));
 
     // Handle associated items within a trait
     if let Some(assoc) = def.as_assoc_item(db) {
@@ -120,31 +158,98 @@ pub(crate) fn def_to_moniker(
             AssocItemContainer::Trait(trait_) => {
                 // Because different traits can have functions with the same name,
                 // we have to include the trait name as part of the moniker for uniqueness.
-                path.push(trait_.name(db));
+                description.push(MonikerDescriptor {
+                    name: trait_.name(db),
+                    desc: MonikerDescriptorKind::Type,
+                });
             }
             AssocItemContainer::Impl(impl_) => {
                 // Because a struct can implement multiple traits, for implementations
                 // we add both the struct name and the trait name to the path
                 if let Some(adt) = impl_.self_ty(db).as_adt() {
-                    path.push(adt.name(db));
+                    description.push(MonikerDescriptor {
+                        name: adt.name(db),
+                        desc: MonikerDescriptorKind::Type,
+                    });
                 }
 
                 if let Some(trait_) = impl_.trait_(db) {
-                    path.push(trait_.name(db));
+                    description.push(MonikerDescriptor {
+                        name: trait_.name(db),
+                        desc: MonikerDescriptorKind::Type,
+                    });
                 }
             }
         }
     }
 
     if let Definition::Field(it) = def {
-        path.push(it.parent_def(db).name(db));
+        description.push(MonikerDescriptor {
+            name: it.parent_def(db).name(db),
+            desc: MonikerDescriptorKind::Type,
+        });
     }
 
-    path.push(def.name(db)?);
+    let name_desc = match def {
+        // These are handled by top-level guard (for performance).
+        Definition::GenericParam(_)
+        | Definition::Label(_)
+        | Definition::DeriveHelper(_)
+        | Definition::BuiltinAttr(_)
+        | Definition::ToolModule(_) => return None,
+
+        Definition::Local(local) => {
+            if !local.is_param(db) {
+                return None;
+            }
+
+            MonikerDescriptor { name: local.name(db), desc: MonikerDescriptorKind::Parameter }
+        }
+        Definition::Macro(m) => {
+            MonikerDescriptor { name: m.name(db), desc: MonikerDescriptorKind::Macro }
+        }
+        Definition::Function(f) => {
+            MonikerDescriptor { name: f.name(db), desc: MonikerDescriptorKind::Method }
+        }
+        Definition::Variant(v) => {
+            MonikerDescriptor { name: v.name(db), desc: MonikerDescriptorKind::Type }
+        }
+        Definition::Const(c) => {
+            MonikerDescriptor { name: c.name(db)?, desc: MonikerDescriptorKind::Term }
+        }
+        Definition::Trait(trait_) => {
+            MonikerDescriptor { name: trait_.name(db), desc: MonikerDescriptorKind::Type }
+        }
+        Definition::TypeAlias(ta) => {
+            MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::TypeParameter }
+        }
+        Definition::Module(m) => {
+            MonikerDescriptor { name: m.name(db)?, desc: MonikerDescriptorKind::Namespace }
+        }
+        Definition::BuiltinType(b) => {
+            MonikerDescriptor { name: b.name(), desc: MonikerDescriptorKind::Type }
+        }
+        Definition::SelfType(imp) => MonikerDescriptor {
+            name: imp.self_ty(db).as_adt()?.name(db),
+            desc: MonikerDescriptorKind::Type,
+        },
+        Definition::Field(it) => {
+            MonikerDescriptor { name: it.name(db), desc: MonikerDescriptorKind::Term }
+        }
+        Definition::Adt(adt) => {
+            MonikerDescriptor { name: adt.name(db), desc: MonikerDescriptorKind::Type }
+        }
+        Definition::Static(s) => {
+            MonikerDescriptor { name: s.name(db), desc: MonikerDescriptorKind::Meta }
+        }
+    };
+
+    description.push(name_desc);
+
     Some(MonikerResult {
         identifier: MonikerIdentifier {
             crate_name: krate.display_name(db)?.crate_name().to_string(),
-            path,
+            description,
         },
         kind: if krate == from_crate { MonikerKind::Export } else { MonikerKind::Import },
         package_information: {
diff --git a/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs
index 29627003600..87b3ef380c5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs
@@ -12,8 +12,9 @@ use ide_db::{
         salsa::{Database, ParallelDatabase, Snapshot},
         Cancelled, CrateGraph, CrateId, SourceDatabase, SourceDatabaseExt,
     },
-    FxHashSet, FxIndexMap,
+    FxIndexMap,
 };
+use stdx::hash::NoHashHashSet;
 
 use crate::RootDatabase;
 
@@ -141,7 +142,7 @@ pub(crate) fn parallel_prime_caches(
     }
 }
 
-fn compute_crates_to_prime(db: &RootDatabase, graph: &CrateGraph) -> FxHashSet<CrateId> {
+fn compute_crates_to_prime(db: &RootDatabase, graph: &CrateGraph) -> NoHashHashSet<CrateId> {
     // We're only interested in the workspace crates and the `ImportMap`s of their direct
     // dependencies, though in practice the latter also compute the `DefMap`s.
     // We don't prime transitive dependencies because they're generally not visible in
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 1a6beec1881..99614b645e4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -14,8 +14,9 @@ use ide_db::{
     base_db::FileId,
     defs::{Definition, NameClass, NameRefClass},
     search::{ReferenceCategory, SearchScope, UsageSearchResult},
-    FxHashMap, RootDatabase,
+    RootDatabase,
 };
+use stdx::hash::NoHashHashMap;
 use syntax::{
     algo::find_node_at_offset,
     ast::{self, HasName},
@@ -29,7 +30,7 @@ use crate::{FilePosition, NavigationTarget, TryToNav};
 #[derive(Debug, Clone)]
 pub struct ReferenceSearchResult {
     pub declaration: Option<Declaration>,
-    pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceCategory>)>>,
+    pub references: NoHashHashMap<FileId, Vec<(TextRange, Option<ReferenceCategory>)>>,
 }
 
 #[derive(Debug, Clone)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index 3fb49b45d98..50371d620eb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -14,7 +14,7 @@ mod html;
 mod tests;
 
 use hir::{Name, Semantics};
-use ide_db::{FxHashMap, RootDatabase};
+use ide_db::{FxHashMap, RootDatabase, SymbolKind};
 use syntax::{
     ast, AstNode, AstToken, NodeOrToken, SyntaxKind::*, SyntaxNode, TextRange, WalkEvent, T,
 };
@@ -24,7 +24,7 @@ use crate::{
         escape::highlight_escape_string, format::highlight_format_string, highlights::Highlights,
         macro_::MacroHighlighter, tags::Highlight,
     },
-    FileId, HlMod, HlTag,
+    FileId, HlMod, HlOperator, HlPunct, HlTag,
 };
 
 pub(crate) use html::highlight_as_html;
@@ -36,6 +36,26 @@ pub struct HlRange {
     pub binding_hash: Option<u64>,
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct HighlightConfig {
+    /// Whether to highlight strings
+    pub strings: bool,
+    /// Whether to highlight punctuation
+    pub punctuation: bool,
+    /// Whether to specialize punctuation highlights
+    pub specialize_punctuation: bool,
+    /// Whether to highlight operator
+    pub operator: bool,
+    /// Whether to specialize operator highlights
+    pub specialize_operator: bool,
+    /// Whether to inject highlights into doc comments
+    pub inject_doc_comment: bool,
+    /// Whether to highlight the macro call bang
+    pub macro_bang: bool,
+    /// Whether to highlight unresolved things be their syntax
+    pub syntactic_name_ref_highlighting: bool,
+}
+
 // Feature: Semantic Syntax Highlighting
 //
 // rust-analyzer highlights the code semantically.
@@ -155,9 +175,9 @@ pub struct HlRange {
 // image::https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png[]
 pub(crate) fn highlight(
     db: &RootDatabase,
+    config: HighlightConfig,
     file_id: FileId,
     range_to_highlight: Option<TextRange>,
-    syntactic_name_ref_highlighting: bool,
 ) -> Vec<HlRange> {
     let _p = profile::span("highlight");
     let sema = Semantics::new(db);
@@ -183,26 +203,18 @@ pub(crate) fn highlight(
         Some(it) => it.krate(),
         None => return hl.to_vec(),
     };
-    traverse(
-        &mut hl,
-        &sema,
-        file_id,
-        &root,
-        krate,
-        range_to_highlight,
-        syntactic_name_ref_highlighting,
-    );
+    traverse(&mut hl, &sema, config, file_id, &root, krate, range_to_highlight);
     hl.to_vec()
 }
 
 fn traverse(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
+    config: HighlightConfig,
     file_id: FileId,
     root: &SyntaxNode,
     krate: hir::Crate,
     range_to_highlight: TextRange,
-    syntactic_name_ref_highlighting: bool,
 ) {
     let is_unlinked = sema.to_module_def(file_id).is_none();
     let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
@@ -323,9 +335,11 @@ fn traverse(
             Enter(it) => it,
             Leave(NodeOrToken::Token(_)) => continue,
             Leave(NodeOrToken::Node(node)) => {
-                // Doc comment highlighting injection, we do this when leaving the node
-                // so that we overwrite the highlighting of the doc comment itself.
-                inject::doc_comment(hl, sema, file_id, &node);
+                if config.inject_doc_comment {
+                    // Doc comment highlighting injection, we do this when leaving the node
+                    // so that we overwrite the highlighting of the doc comment itself.
+                    inject::doc_comment(hl, sema, config, file_id, &node);
+                }
                 continue;
             }
         };
@@ -400,7 +414,8 @@ fn traverse(
                 let string_to_highlight = ast::String::cast(descended_token.clone());
                 if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
                     if string.is_raw() {
-                        if inject::ra_fixture(hl, sema, &string, &expanded_string).is_some() {
+                        if inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some()
+                        {
                             continue;
                         }
                     }
@@ -421,7 +436,7 @@ fn traverse(
                 sema,
                 krate,
                 &mut bindings_shadow_count,
-                syntactic_name_ref_highlighting,
+                config.syntactic_name_ref_highlighting,
                 name_like,
             ),
             NodeOrToken::Token(token) => highlight::token(sema, token).zip(Some(None)),
@@ -439,6 +454,29 @@ fn traverse(
                 // something unresolvable. FIXME: There should be a way to prevent that
                 continue;
             }
+
+            // apply config filtering
+            match &mut highlight.tag {
+                HlTag::StringLiteral if !config.strings => continue,
+                // If punctuation is disabled, make the macro bang part of the macro call again.
+                tag @ HlTag::Punctuation(HlPunct::MacroBang) => {
+                    if !config.macro_bang {
+                        *tag = HlTag::Symbol(SymbolKind::Macro);
+                    } else if !config.specialize_punctuation {
+                        *tag = HlTag::Punctuation(HlPunct::Other);
+                    }
+                }
+                HlTag::Punctuation(_) if !config.punctuation => continue,
+                tag @ HlTag::Punctuation(_) if !config.specialize_punctuation => {
+                    *tag = HlTag::Punctuation(HlPunct::Other);
+                }
+                HlTag::Operator(_) if !config.operator && highlight.mods.is_empty() => continue,
+                tag @ HlTag::Operator(_) if !config.specialize_operator => {
+                    *tag = HlTag::Operator(HlOperator::Other);
+                }
+                _ => (),
+            }
+
             if inside_attribute {
                 highlight |= HlMod::Attribute
             }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
index 9777c014c7a..e91fd7f1257 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
@@ -5,7 +5,10 @@ use oorandom::Rand32;
 use stdx::format_to;
 use syntax::AstNode;
 
-use crate::{syntax_highlighting::highlight, FileId, RootDatabase};
+use crate::{
+    syntax_highlighting::{highlight, HighlightConfig},
+    FileId, RootDatabase,
+};
 
 pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String {
     let parse = db.parse(file_id);
@@ -20,7 +23,21 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
         )
     }
 
-    let hl_ranges = highlight(db, file_id, None, false);
+    let hl_ranges = highlight(
+        db,
+        HighlightConfig {
+            strings: true,
+            punctuation: true,
+            specialize_punctuation: true,
+            specialize_operator: true,
+            operator: true,
+            inject_doc_comment: true,
+            macro_bang: true,
+            syntactic_name_ref_highlighting: false,
+        },
+        file_id,
+        None,
+    );
     let text = parse.tree().syntax().to_string();
     let mut buf = String::new();
     buf.push_str(STYLE);
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
index f376f9fda7a..9139528c7ed 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
@@ -15,13 +15,14 @@ use syntax::{
 
 use crate::{
     doc_links::{doc_attributes, extract_definitions_from_docs, resolve_doc_path_for_def},
-    syntax_highlighting::{highlights::Highlights, injector::Injector},
+    syntax_highlighting::{highlights::Highlights, injector::Injector, HighlightConfig},
     Analysis, HlMod, HlRange, HlTag, RootDatabase,
 };
 
 pub(super) fn ra_fixture(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
+    config: HighlightConfig,
     literal: &ast::String,
     expanded: &ast::String,
 ) -> Option<()> {
@@ -63,7 +64,13 @@ pub(super) fn ra_fixture(
 
     let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text());
 
-    for mut hl_range in analysis.highlight(tmp_file_id).unwrap() {
+    for mut hl_range in analysis
+        .highlight(
+            HighlightConfig { syntactic_name_ref_highlighting: false, ..config },
+            tmp_file_id,
+        )
+        .unwrap()
+    {
         for range in inj.map_range_up(hl_range.range) {
             if let Some(range) = literal.map_range_up(range) {
                 hl_range.range = range;
@@ -86,6 +93,7 @@ const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
 pub(super) fn doc_comment(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
+    config: HighlightConfig,
     src_file_id: FileId,
     node: &SyntaxNode,
 ) {
@@ -206,7 +214,14 @@ pub(super) fn doc_comment(
 
     let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text());
 
-    if let Ok(ranges) = analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)) {
+    if let Ok(ranges) = analysis.with_db(|db| {
+        super::highlight(
+            db,
+            HighlightConfig { syntactic_name_ref_highlighting: true, ..config },
+            tmp_file_id,
+            None,
+        )
+    }) {
         for HlRange { range, highlight, binding_hash } in ranges {
             for range in inj.map_range_up(range) {
                 hl.add(HlRange { range, highlight: highlight | HlMod::Injected, binding_hash });
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
index 5262770f303..3949f1189bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
@@ -199,7 +199,7 @@ impl fmt::Display for HlTag {
 }
 
 impl HlMod {
-    const ALL: &'static [HlMod; HlMod::Unsafe as u8 as usize + 1] = &[
+    const ALL: &'static [HlMod; 19] = &[
         HlMod::Associated,
         HlMod::Async,
         HlMod::Attribute,
@@ -296,7 +296,7 @@ impl Highlight {
         Highlight { tag, mods: HlMods::default() }
     }
     pub fn is_empty(&self) -> bool {
-        self.tag == HlTag::None && self.mods == HlMods::default()
+        self.tag == HlTag::None && self.mods.is_empty()
     }
 }
 
@@ -330,6 +330,10 @@ impl ops::BitOr<HlMod> for Highlight {
 }
 
 impl HlMods {
+    pub fn is_empty(&self) -> bool {
+        self.0 == 0
+    }
+
     pub fn contains(self, m: HlMod) -> bool {
         self.0 & m.mask() == m.mask()
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index a747b4bc1f9..eef5baea983 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -56,7 +56,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="field declaration">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span><span class="comma">,</span>
 <span class="brace">}</span>
 
-<span class="comment documentation">/// This is an impl with a code block.</span>
+<span class="comment documentation">/// This is an impl of </span><span class="struct documentation injected intra_doc_link">[`Foo`]</span><span class="comment documentation"> with a code block.</span>
 <span class="comment documentation">///</span>
 <span class="comment documentation">/// ```</span>
 <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 382735cb368..46cc667fc45 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -4,7 +4,18 @@ use expect_test::{expect_file, ExpectFile};
 use ide_db::SymbolKind;
 use test_utils::{bench, bench_fixture, skip_slow_tests, AssertLinear};
 
-use crate::{fixture, FileRange, HlTag, TextRange};
+use crate::{fixture, FileRange, HighlightConfig, HlTag, TextRange};
+
+const HL_CONFIG: HighlightConfig = HighlightConfig {
+    strings: true,
+    punctuation: true,
+    specialize_punctuation: true,
+    specialize_operator: true,
+    operator: true,
+    inject_doc_comment: true,
+    macro_bang: true,
+    syntactic_name_ref_highlighting: false,
+};
 
 #[test]
 fn attributes() {
@@ -613,7 +624,7 @@ struct Foo {
     bar: bool,
 }
 
-/// This is an impl with a code block.
+/// This is an impl of [`Foo`] with a code block.
 ///
 /// ```
 /// fn foo() {
@@ -996,7 +1007,10 @@ struct Foo {
 
     // The "x"
     let highlights = &analysis
-        .highlight_range(FileRange { file_id, range: TextRange::at(45.into(), 1.into()) })
+        .highlight_range(
+            HL_CONFIG,
+            FileRange { file_id, range: TextRange::at(45.into(), 1.into()) },
+        )
         .unwrap();
 
     assert_eq!(&highlights[0].highlight.to_string(), "field.declaration.public");
@@ -1011,7 +1025,7 @@ macro_rules! test {}
 }"#
         .trim(),
     );
-    let _ = analysis.highlight(file_id).unwrap();
+    let _ = analysis.highlight(HL_CONFIG, file_id).unwrap();
 }
 
 /// Highlights the code given by the `ra_fixture` argument, renders the
@@ -1035,7 +1049,7 @@ fn benchmark_syntax_highlighting_long_struct() {
     let hash = {
         let _pt = bench("syntax highlighting long struct");
         analysis
-            .highlight(file_id)
+            .highlight(HL_CONFIG, file_id)
             .unwrap()
             .iter()
             .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
@@ -1061,7 +1075,7 @@ fn syntax_highlighting_not_quadratic() {
             let time = Instant::now();
 
             let hash = analysis
-                .highlight(file_id)
+                .highlight(HL_CONFIG, file_id)
                 .unwrap()
                 .iter()
                 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
@@ -1086,7 +1100,7 @@ fn benchmark_syntax_highlighting_parser() {
     let hash = {
         let _pt = bench("syntax highlighting parser");
         analysis
-            .highlight(file_id)
+            .highlight(HL_CONFIG, file_id)
             .unwrap()
             .iter()
             .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
index bf7b7efe282..17a1e385b77 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
@@ -3,8 +3,9 @@ use std::sync::Arc;
 use dot::{Id, LabelText};
 use ide_db::{
     base_db::{CrateGraph, CrateId, Dependency, SourceDatabase, SourceDatabaseExt},
-    FxHashSet, RootDatabase,
+    RootDatabase,
 };
+use stdx::hash::NoHashHashSet;
 
 // Feature: View Crate Graph
 //
@@ -41,7 +42,7 @@ pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result<String,
 
 struct DotCrateGraph {
     graph: Arc<CrateGraph>,
-    crates_to_render: FxHashSet<CrateId>,
+    crates_to_render: NoHashHashSet<CrateId>,
 }
 
 type Edge<'a> = (CrateId, &'a Dependency);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
index 7e21a808da0..bc1224af9b2 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
@@ -13,6 +13,8 @@ pub(super) const PATTERN_FIRST: TokenSet =
         T![.],
     ]));
 
+const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
+
 pub(crate) fn pattern(p: &mut Parser<'_>) {
     pattern_r(p, PAT_RECOVERY_SET);
 }
@@ -228,6 +230,7 @@ fn path_or_macro_pat(p: &mut Parser<'_>) -> CompletedMarker {
 //     let S(_) = ();
 //     let S(_,) = ();
 //     let S(_, .. , x) = ();
+//     let S(| a) = ();
 // }
 fn tuple_pat_fields(p: &mut Parser<'_>) {
     assert!(p.at(T!['(']));
@@ -363,6 +366,7 @@ fn ref_pat(p: &mut Parser<'_>) -> CompletedMarker {
 //     let (a,) = ();
 //     let (..) = ();
 //     let () = ();
+//     let (| a | a, | b) = ((),());
 // }
 fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
     assert!(p.at(T!['(']));
@@ -373,13 +377,13 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
     let mut has_rest = false;
     while !p.at(EOF) && !p.at(T![')']) {
         has_pat = true;
-        if !p.at_ts(PATTERN_FIRST) {
+        if !p.at_ts(PAT_TOP_FIRST) {
             p.error("expected a pattern");
             break;
         }
         has_rest |= p.at(T![..]);
 
-        pattern(p);
+        pattern_top(p);
         if !p.at(T![')']) {
             has_comma = true;
             p.expect(T![,]);
@@ -393,6 +397,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
 // test slice_pat
 // fn main() {
 //     let [a, b, ..] = [];
+//     let [| a, ..] = [];
 // }
 fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
     assert!(p.at(T!['[']));
@@ -405,12 +410,12 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
 
 fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
     while !p.at(EOF) && !p.at(ket) {
-        if !p.at_ts(PATTERN_FIRST) {
+        if !p.at_ts(PAT_TOP_FIRST) {
             p.error("expected a pattern");
             break;
         }
 
-        pattern(p);
+        pattern_top(p);
         if !p.at(ket) {
             p.expect(T![,]);
         }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast
index 235a9d7f404..dff72ba886f 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast
@@ -37,6 +37,29 @@ SOURCE_FILE
             L_BRACK "["
             R_BRACK "]"
           SEMICOLON ";"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          SLICE_PAT
+            L_BRACK "["
+            PIPE "|"
+            WHITESPACE " "
+            IDENT_PAT
+              NAME
+                IDENT "a"
+            COMMA ","
+            WHITESPACE " "
+            REST_PAT
+              DOT2 ".."
+            R_BRACK "]"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          ARRAY_EXPR
+            L_BRACK "["
+            R_BRACK "]"
+          SEMICOLON ";"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs
index 7955973b952..855ba89b1e9 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs
@@ -1,3 +1,4 @@
 fn main() {
     let [a, b, ..] = [];
+    let [| a, ..] = [];
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
index 3cdaf32b572..55baf2fdcb4 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
@@ -100,6 +100,29 @@ SOURCE_FILE
             L_PAREN "("
             R_PAREN ")"
           SEMICOLON ";"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          TUPLE_STRUCT_PAT
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "S"
+            L_PAREN "("
+            PIPE "|"
+            WHITESPACE " "
+            IDENT_PAT
+              NAME
+                IDENT "a"
+            R_PAREN ")"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          TUPLE_EXPR
+            L_PAREN "("
+            R_PAREN ")"
+          SEMICOLON ";"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
index 0dfe6362967..8ec6f4ca93e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
@@ -3,4 +3,5 @@ fn foo() {
     let S(_) = ();
     let S(_,) = ();
     let S(_, .. , x) = ();
+    let S(| a) = ();
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast
index cebe98c43aa..1a01e0f6938 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast
@@ -85,6 +85,46 @@ SOURCE_FILE
             L_PAREN "("
             R_PAREN ")"
           SEMICOLON ";"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          TUPLE_PAT
+            L_PAREN "("
+            PIPE "|"
+            WHITESPACE " "
+            OR_PAT
+              IDENT_PAT
+                NAME
+                  IDENT "a"
+              WHITESPACE " "
+              PIPE "|"
+              WHITESPACE " "
+              IDENT_PAT
+                NAME
+                  IDENT "a"
+            COMMA ","
+            WHITESPACE " "
+            PIPE "|"
+            WHITESPACE " "
+            IDENT_PAT
+              NAME
+                IDENT "b"
+            R_PAREN ")"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          TUPLE_EXPR
+            L_PAREN "("
+            TUPLE_EXPR
+              L_PAREN "("
+              R_PAREN ")"
+            COMMA ","
+            TUPLE_EXPR
+              L_PAREN "("
+              R_PAREN ")"
+            R_PAREN ")"
+          SEMICOLON ";"
         WHITESPACE "\n"
         R_CURLY "}"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs
index ba719879d4c..fbd7f48f66b 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs
@@ -3,4 +3,5 @@ fn main() {
     let (a,) = ();
     let (..) = ();
     let () = ();
+    let (| a | a, | b) = ((),());
 }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index 5746eac0b37..e39026ac70b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -24,7 +24,6 @@ tt = { path = "../tt", version = "0.0.0" }
 mbe = { path = "../mbe", version = "0.0.0" }
 paths = { path = "../paths", version = "0.0.0" }
 proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
-crossbeam = "0.8.1"
 
 [dev-dependencies]
 expect-test = "1.4.0"
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
index 4c205b9cada..3679bfc43c9 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
@@ -26,6 +26,7 @@ use std::{
     ffi::OsString,
     fs,
     path::{Path, PathBuf},
+    thread,
     time::SystemTime,
 };
 
@@ -65,18 +66,16 @@ impl ProcMacroSrv {
 
         let macro_body = task.macro_body.to_subtree();
         let attributes = task.attributes.map(|it| it.to_subtree());
-        // FIXME: replace this with std's scoped threads once they stabilize
-        // (then remove dependency on crossbeam)
-        let result = crossbeam::scope(|s| {
-            let res = match s
-                .builder()
+        let result = thread::scope(|s| {
+            let thread = thread::Builder::new()
                 .stack_size(EXPANDER_STACK_SIZE)
                 .name(task.macro_name.clone())
-                .spawn(|_| {
+                .spawn_scoped(s, || {
                     expander
                         .expand(&task.macro_name, &macro_body, attributes.as_ref())
                         .map(|it| FlatTree::new(&it))
-                }) {
+                });
+            let res = match thread {
                 Ok(handle) => handle.join(),
                 Err(e) => std::panic::resume_unwind(Box::new(e)),
             };
@@ -86,10 +85,6 @@ impl ProcMacroSrv {
                 Err(e) => std::panic::resume_unwind(e),
             }
         });
-        let result = match result {
-            Ok(result) => result,
-            Err(e) => std::panic::resume_unwind(e),
-        };
 
         prev_env.rollback();
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index 8d0fa757c2e..9ccb6e9101e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -185,10 +185,10 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        2,
+                        1,
                     ): CrateData {
                         root_file_id: FileId(
-                            3,
+                            2,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -197,9 +197,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "an_example",
+                                    "hello_world",
                                 ),
-                                canonical_name: "an-example",
+                                canonical_name: "hello-world",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -260,77 +260,85 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        4,
+                        2,
                     ): CrateData {
                         root_file_id: FileId(
-                            5,
+                            3,
                         ),
-                        edition: Edition2015,
+                        edition: Edition2018,
                         version: Some(
-                            "0.2.98",
+                            "0.1.0",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "libc",
+                                    "an_example",
                                 ),
-                                canonical_name: "libc",
+                                canonical_name: "an-example",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=default",
-                                "feature=std",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=align",
-                                "feature=const-extern-fn",
-                                "feature=default",
-                                "feature=extra_traits",
-                                "feature=rustc-dep-of-std",
-                                "feature=std",
-                                "feature=use_std",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                                "CARGO_PKG_VERSION": "0.2.98",
+                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                                "CARGO_PKG_VERSION": "0.1.0",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "libc",
+                                "CARGO_CRATE_NAME": "hello_world",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "libc",
-                                "CARGO_PKG_VERSION_PATCH": "98",
+                                "CARGO_PKG_NAME": "hello-world",
+                                "CARGO_PKG_VERSION_PATCH": "0",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "2",
+                                "CARGO_PKG_VERSION_MINOR": "1",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [],
+                        dependencies: [
+                            Dependency {
+                                crate_id: CrateId(
+                                    0,
+                                ),
+                                name: CrateName(
+                                    "hello_world",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    4,
+                                ),
+                                name: CrateName(
+                                    "libc",
+                                ),
+                                prelude: true,
+                            },
+                        ],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: Some(
-                                "https://github.com/rust-lang/libc",
-                            ),
+                            repo: None,
                         },
                         is_proc_macro: false,
                     },
                     CrateId(
-                        1,
+                        3,
                     ): CrateData {
                         root_file_id: FileId(
-                            2,
+                            4,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -339,9 +347,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "hello_world",
+                                    "it",
                                 ),
-                                canonical_name: "hello-world",
+                                canonical_name: "it",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -402,77 +410,69 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        3,
+                        4,
                     ): CrateData {
                         root_file_id: FileId(
-                            4,
+                            5,
                         ),
-                        edition: Edition2018,
+                        edition: Edition2015,
                         version: Some(
-                            "0.1.0",
+                            "0.2.98",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "it",
+                                    "libc",
                                 ),
-                                canonical_name: "it",
+                                canonical_name: "libc",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
+                                "feature=default",
+                                "feature=std",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
+                                "feature=align",
+                                "feature=const-extern-fn",
+                                "feature=default",
+                                "feature=extra_traits",
+                                "feature=rustc-dep-of-std",
+                                "feature=std",
+                                "feature=use_std",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                                "CARGO_PKG_VERSION": "0.1.0",
+                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                                "CARGO_PKG_VERSION": "0.2.98",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "hello_world",
+                                "CARGO_CRATE_NAME": "libc",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "hello-world",
-                                "CARGO_PKG_VERSION_PATCH": "0",
+                                "CARGO_PKG_NAME": "libc",
+                                "CARGO_PKG_VERSION_PATCH": "98",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "1",
+                                "CARGO_PKG_VERSION_MINOR": "2",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [
-                            Dependency {
-                                crate_id: CrateId(
-                                    0,
-                                ),
-                                name: CrateName(
-                                    "hello_world",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    4,
-                                ),
-                                name: CrateName(
-                                    "libc",
-                                ),
-                                prelude: true,
-                            },
-                        ],
+                        dependencies: [],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: None,
+                            repo: Some(
+                                "https://github.com/rust-lang/libc",
+                            ),
                         },
                         is_proc_macro: false,
                     },
@@ -567,10 +567,10 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        2,
+                        1,
                     ): CrateData {
                         root_file_id: FileId(
-                            3,
+                            2,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -579,9 +579,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "an_example",
+                                    "hello_world",
                                 ),
-                                canonical_name: "an-example",
+                                canonical_name: "hello-world",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -644,77 +644,87 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        4,
+                        2,
                     ): CrateData {
                         root_file_id: FileId(
-                            5,
+                            3,
                         ),
-                        edition: Edition2015,
+                        edition: Edition2018,
                         version: Some(
-                            "0.2.98",
+                            "0.1.0",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "libc",
+                                    "an_example",
                                 ),
-                                canonical_name: "libc",
+                                canonical_name: "an-example",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=default",
-                                "feature=std",
+                                "test",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=align",
-                                "feature=const-extern-fn",
-                                "feature=default",
-                                "feature=extra_traits",
-                                "feature=rustc-dep-of-std",
-                                "feature=std",
-                                "feature=use_std",
+                                "test",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                                "CARGO_PKG_VERSION": "0.2.98",
+                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                                "CARGO_PKG_VERSION": "0.1.0",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "libc",
+                                "CARGO_CRATE_NAME": "hello_world",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "libc",
-                                "CARGO_PKG_VERSION_PATCH": "98",
+                                "CARGO_PKG_NAME": "hello-world",
+                                "CARGO_PKG_VERSION_PATCH": "0",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "2",
+                                "CARGO_PKG_VERSION_MINOR": "1",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [],
+                        dependencies: [
+                            Dependency {
+                                crate_id: CrateId(
+                                    0,
+                                ),
+                                name: CrateName(
+                                    "hello_world",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    4,
+                                ),
+                                name: CrateName(
+                                    "libc",
+                                ),
+                                prelude: true,
+                            },
+                        ],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: Some(
-                                "https://github.com/rust-lang/libc",
-                            ),
+                            repo: None,
                         },
                         is_proc_macro: false,
                     },
                     CrateId(
-                        1,
+                        3,
                     ): CrateData {
                         root_file_id: FileId(
-                            2,
+                            4,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -723,9 +733,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "hello_world",
+                                    "it",
                                 ),
-                                canonical_name: "hello-world",
+                                canonical_name: "it",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -788,79 +798,69 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        3,
+                        4,
                     ): CrateData {
                         root_file_id: FileId(
-                            4,
+                            5,
                         ),
-                        edition: Edition2018,
+                        edition: Edition2015,
                         version: Some(
-                            "0.1.0",
+                            "0.2.98",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "it",
+                                    "libc",
                                 ),
-                                canonical_name: "it",
+                                canonical_name: "libc",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "test",
+                                "feature=default",
+                                "feature=std",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "test",
+                                "feature=align",
+                                "feature=const-extern-fn",
+                                "feature=default",
+                                "feature=extra_traits",
+                                "feature=rustc-dep-of-std",
+                                "feature=std",
+                                "feature=use_std",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                                "CARGO_PKG_VERSION": "0.1.0",
+                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                                "CARGO_PKG_VERSION": "0.2.98",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "hello_world",
+                                "CARGO_CRATE_NAME": "libc",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "hello-world",
-                                "CARGO_PKG_VERSION_PATCH": "0",
+                                "CARGO_PKG_NAME": "libc",
+                                "CARGO_PKG_VERSION_PATCH": "98",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "1",
+                                "CARGO_PKG_VERSION_MINOR": "2",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [
-                            Dependency {
-                                crate_id: CrateId(
-                                    0,
-                                ),
-                                name: CrateName(
-                                    "hello_world",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    4,
-                                ),
-                                name: CrateName(
-                                    "libc",
-                                ),
-                                prelude: true,
-                            },
-                        ],
+                        dependencies: [],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: None,
+                            repo: Some(
+                                "https://github.com/rust-lang/libc",
+                            ),
                         },
                         is_proc_macro: false,
                     },
@@ -946,10 +946,10 @@ fn cargo_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        2,
+                        1,
                     ): CrateData {
                         root_file_id: FileId(
-                            3,
+                            2,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -958,9 +958,9 @@ fn cargo_hello_world_project_model() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "an_example",
+                                    "hello_world",
                                 ),
-                                canonical_name: "an-example",
+                                canonical_name: "hello-world",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1023,77 +1023,87 @@ fn cargo_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        4,
+                        2,
                     ): CrateData {
                         root_file_id: FileId(
-                            5,
+                            3,
                         ),
-                        edition: Edition2015,
+                        edition: Edition2018,
                         version: Some(
-                            "0.2.98",
+                            "0.1.0",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "libc",
+                                    "an_example",
                                 ),
-                                canonical_name: "libc",
+                                canonical_name: "an-example",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=default",
-                                "feature=std",
+                                "test",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "feature=align",
-                                "feature=const-extern-fn",
-                                "feature=default",
-                                "feature=extra_traits",
-                                "feature=rustc-dep-of-std",
-                                "feature=std",
-                                "feature=use_std",
+                                "test",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                                "CARGO_PKG_VERSION": "0.2.98",
+                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                                "CARGO_PKG_VERSION": "0.1.0",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "libc",
+                                "CARGO_CRATE_NAME": "hello_world",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "libc",
-                                "CARGO_PKG_VERSION_PATCH": "98",
+                                "CARGO_PKG_NAME": "hello-world",
+                                "CARGO_PKG_VERSION_PATCH": "0",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "2",
+                                "CARGO_PKG_VERSION_MINOR": "1",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [],
+                        dependencies: [
+                            Dependency {
+                                crate_id: CrateId(
+                                    0,
+                                ),
+                                name: CrateName(
+                                    "hello_world",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    4,
+                                ),
+                                name: CrateName(
+                                    "libc",
+                                ),
+                                prelude: true,
+                            },
+                        ],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: Some(
-                                "https://github.com/rust-lang/libc",
-                            ),
+                            repo: None,
                         },
                         is_proc_macro: false,
                     },
                     CrateId(
-                        1,
+                        3,
                     ): CrateData {
                         root_file_id: FileId(
-                            2,
+                            4,
                         ),
                         edition: Edition2018,
                         version: Some(
@@ -1102,9 +1112,9 @@ fn cargo_hello_world_project_model() {
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "hello_world",
+                                    "it",
                                 ),
-                                canonical_name: "hello-world",
+                                canonical_name: "it",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1167,79 +1177,69 @@ fn cargo_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        3,
+                        4,
                     ): CrateData {
                         root_file_id: FileId(
-                            4,
+                            5,
                         ),
-                        edition: Edition2018,
+                        edition: Edition2015,
                         version: Some(
-                            "0.1.0",
+                            "0.2.98",
                         ),
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "it",
+                                    "libc",
                                 ),
-                                canonical_name: "it",
+                                canonical_name: "libc",
                             },
                         ),
                         cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "test",
+                                "feature=default",
+                                "feature=std",
                             ],
                         ),
                         potential_cfg_options: CfgOptions(
                             [
                                 "debug_assertions",
-                                "test",
+                                "feature=align",
+                                "feature=const-extern-fn",
+                                "feature=default",
+                                "feature=extra_traits",
+                                "feature=rustc-dep-of-std",
+                                "feature=std",
+                                "feature=use_std",
                             ],
                         ),
                         env: Env {
                             entries: {
                                 "CARGO_PKG_LICENSE": "",
                                 "CARGO_PKG_VERSION_MAJOR": "0",
-                                "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                                "CARGO_PKG_VERSION": "0.1.0",
+                                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                                "CARGO_PKG_VERSION": "0.2.98",
                                 "CARGO_PKG_AUTHORS": "",
-                                "CARGO_CRATE_NAME": "hello_world",
+                                "CARGO_CRATE_NAME": "libc",
                                 "CARGO_PKG_LICENSE_FILE": "",
                                 "CARGO_PKG_HOMEPAGE": "",
                                 "CARGO_PKG_DESCRIPTION": "",
-                                "CARGO_PKG_NAME": "hello-world",
-                                "CARGO_PKG_VERSION_PATCH": "0",
+                                "CARGO_PKG_NAME": "libc",
+                                "CARGO_PKG_VERSION_PATCH": "98",
                                 "CARGO": "cargo",
                                 "CARGO_PKG_REPOSITORY": "",
-                                "CARGO_PKG_VERSION_MINOR": "1",
+                                "CARGO_PKG_VERSION_MINOR": "2",
                                 "CARGO_PKG_VERSION_PRE": "",
                             },
                         },
-                        dependencies: [
-                            Dependency {
-                                crate_id: CrateId(
-                                    0,
-                                ),
-                                name: CrateName(
-                                    "hello_world",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    4,
-                                ),
-                                name: CrateName(
-                                    "libc",
-                                ),
-                                prelude: true,
-                            },
-                        ],
+                        dependencies: [],
                         proc_macro: Err(
                             "crate has not (yet) been built",
                         ),
                         origin: CratesIo {
-                            repo: None,
+                            repo: Some(
+                                "https://github.com/rust-lang/libc",
+                            ),
                         },
                         is_proc_macro: false,
                     },
@@ -1301,19 +1301,53 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        10,
+                        1,
                     ): CrateData {
                         root_file_id: FileId(
-                            11,
+                            2,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "unwind",
+                                    "core",
                                 ),
-                                canonical_name: "unwind",
+                                canonical_name: "core",
+                            },
+                        ),
+                        cfg_options: CfgOptions(
+                            [],
+                        ),
+                        potential_cfg_options: CfgOptions(
+                            [],
+                        ),
+                        env: Env {
+                            entries: {},
+                        },
+                        dependencies: [],
+                        proc_macro: Err(
+                            "no proc macro loaded for sysroot crate",
+                        ),
+                        origin: Lang(
+                            Core,
+                        ),
+                        is_proc_macro: false,
+                    },
+                    CrateId(
+                        2,
+                    ): CrateData {
+                        root_file_id: FileId(
+                            3,
+                        ),
+                        edition: Edition2018,
+                        version: None,
+                        display_name: Some(
+                            CrateDisplayName {
+                                crate_name: CrateName(
+                                    "panic_abort",
+                                ),
+                                canonical_name: "panic_abort",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1335,19 +1369,19 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        7,
+                        3,
                     ): CrateData {
                         root_file_id: FileId(
-                            8,
+                            4,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "std_detect",
+                                    "panic_unwind",
                                 ),
-                                canonical_name: "std_detect",
+                                canonical_name: "panic_unwind",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1413,19 +1447,19 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        1,
+                        5,
                     ): CrateData {
                         root_file_id: FileId(
-                            2,
+                            6,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "core",
+                                    "profiler_builtins",
                                 ),
-                                canonical_name: "core",
+                                canonical_name: "profiler_builtins",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1442,24 +1476,24 @@ fn rust_project_hello_world_project_model() {
                             "no proc macro loaded for sysroot crate",
                         ),
                         origin: Lang(
-                            Core,
+                            Other,
                         ),
                         is_proc_macro: false,
                     },
                     CrateId(
-                        11,
+                        6,
                     ): CrateData {
                         root_file_id: FileId(
-                            12,
+                            7,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "hello_world",
+                                    "std",
                                 ),
-                                canonical_name: "hello_world",
+                                canonical_name: "std",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1474,6 +1508,15 @@ fn rust_project_hello_world_project_model() {
                         dependencies: [
                             Dependency {
                                 crate_id: CrateId(
+                                    0,
+                                ),
+                                name: CrateName(
+                                    "alloc",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
                                     1,
                                 ),
                                 name: CrateName(
@@ -1483,19 +1526,46 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    0,
+                                    2,
                                 ),
                                 name: CrateName(
-                                    "alloc",
+                                    "panic_abort",
                                 ),
                                 prelude: true,
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    6,
+                                    3,
                                 ),
                                 name: CrateName(
-                                    "std",
+                                    "panic_unwind",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    5,
+                                ),
+                                name: CrateName(
+                                    "profiler_builtins",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    7,
+                                ),
+                                name: CrateName(
+                                    "std_detect",
+                                ),
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    8,
+                                ),
+                                name: CrateName(
+                                    "term",
                                 ),
                                 prelude: true,
                             },
@@ -1506,31 +1576,40 @@ fn rust_project_hello_world_project_model() {
                                 name: CrateName(
                                     "test",
                                 ),
-                                prelude: false,
+                                prelude: true,
+                            },
+                            Dependency {
+                                crate_id: CrateId(
+                                    10,
+                                ),
+                                name: CrateName(
+                                    "unwind",
+                                ),
+                                prelude: true,
                             },
                         ],
                         proc_macro: Err(
-                            "no proc macro dylib present",
+                            "no proc macro loaded for sysroot crate",
+                        ),
+                        origin: Lang(
+                            Std,
                         ),
-                        origin: CratesIo {
-                            repo: None,
-                        },
                         is_proc_macro: false,
                     },
                     CrateId(
-                        8,
+                        7,
                     ): CrateData {
                         root_file_id: FileId(
-                            9,
+                            8,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "term",
+                                    "std_detect",
                                 ),
-                                canonical_name: "term",
+                                canonical_name: "std_detect",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1552,19 +1631,19 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        5,
+                        8,
                     ): CrateData {
                         root_file_id: FileId(
-                            6,
+                            9,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "profiler_builtins",
+                                    "term",
                                 ),
-                                canonical_name: "profiler_builtins",
+                                canonical_name: "term",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1586,19 +1665,19 @@ fn rust_project_hello_world_project_model() {
                         is_proc_macro: false,
                     },
                     CrateId(
-                        2,
+                        9,
                     ): CrateData {
                         root_file_id: FileId(
-                            3,
+                            10,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "panic_abort",
+                                    "test",
                                 ),
-                                canonical_name: "panic_abort",
+                                canonical_name: "test",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1615,24 +1694,24 @@ fn rust_project_hello_world_project_model() {
                             "no proc macro loaded for sysroot crate",
                         ),
                         origin: Lang(
-                            Other,
+                            Test,
                         ),
                         is_proc_macro: false,
                     },
                     CrateId(
-                        9,
+                        10,
                     ): CrateData {
                         root_file_id: FileId(
-                            10,
+                            11,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "test",
+                                    "unwind",
                                 ),
-                                canonical_name: "test",
+                                canonical_name: "unwind",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1649,24 +1728,24 @@ fn rust_project_hello_world_project_model() {
                             "no proc macro loaded for sysroot crate",
                         ),
                         origin: Lang(
-                            Test,
+                            Other,
                         ),
                         is_proc_macro: false,
                     },
                     CrateId(
-                        6,
+                        11,
                     ): CrateData {
                         root_file_id: FileId(
-                            7,
+                            12,
                         ),
                         edition: Edition2018,
                         version: None,
                         display_name: Some(
                             CrateDisplayName {
                                 crate_name: CrateName(
-                                    "std",
+                                    "hello_world",
                                 ),
-                                canonical_name: "std",
+                                canonical_name: "hello_world",
                             },
                         ),
                         cfg_options: CfgOptions(
@@ -1681,15 +1760,6 @@ fn rust_project_hello_world_project_model() {
                         dependencies: [
                             Dependency {
                                 crate_id: CrateId(
-                                    0,
-                                ),
-                                name: CrateName(
-                                    "alloc",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
                                     1,
                                 ),
                                 name: CrateName(
@@ -1699,46 +1769,19 @@ fn rust_project_hello_world_project_model() {
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    2,
-                                ),
-                                name: CrateName(
-                                    "panic_abort",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    3,
-                                ),
-                                name: CrateName(
-                                    "panic_unwind",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    5,
-                                ),
-                                name: CrateName(
-                                    "profiler_builtins",
-                                ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    7,
+                                    0,
                                 ),
                                 name: CrateName(
-                                    "std_detect",
+                                    "alloc",
                                 ),
                                 prelude: true,
                             },
                             Dependency {
                                 crate_id: CrateId(
-                                    8,
+                                    6,
                                 ),
                                 name: CrateName(
-                                    "term",
+                                    "std",
                                 ),
                                 prelude: true,
                             },
@@ -1749,58 +1792,15 @@ fn rust_project_hello_world_project_model() {
                                 name: CrateName(
                                     "test",
                                 ),
-                                prelude: true,
-                            },
-                            Dependency {
-                                crate_id: CrateId(
-                                    10,
-                                ),
-                                name: CrateName(
-                                    "unwind",
-                                ),
-                                prelude: true,
+                                prelude: false,
                             },
                         ],
                         proc_macro: Err(
-                            "no proc macro loaded for sysroot crate",
-                        ),
-                        origin: Lang(
-                            Std,
-                        ),
-                        is_proc_macro: false,
-                    },
-                    CrateId(
-                        3,
-                    ): CrateData {
-                        root_file_id: FileId(
-                            4,
-                        ),
-                        edition: Edition2018,
-                        version: None,
-                        display_name: Some(
-                            CrateDisplayName {
-                                crate_name: CrateName(
-                                    "panic_unwind",
-                                ),
-                                canonical_name: "panic_unwind",
-                            },
-                        ),
-                        cfg_options: CfgOptions(
-                            [],
-                        ),
-                        potential_cfg_options: CfgOptions(
-                            [],
+                            "no proc macro dylib present",
                         ),
-                        env: Env {
-                            entries: {},
+                        origin: CratesIo {
+                            repo: None,
                         },
-                        dependencies: [],
-                        proc_macro: Err(
-                            "no proc macro loaded for sysroot crate",
-                        ),
-                        origin: Lang(
-                            Other,
-                        ),
                         is_proc_macro: false,
                     },
                 },
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index 8d6f50f5587..818bbed6af2 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -13,7 +13,7 @@ use cfg::{CfgDiff, CfgOptions};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use semver::Version;
-use stdx::always;
+use stdx::{always, hash::NoHashHashMap};
 
 use crate::{
     build_scripts::BuildScriptOutput,
@@ -471,7 +471,7 @@ fn project_json_to_crate_graph(
         .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load));
 
     let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
-    let crates: FxHashMap<CrateId, CrateId> = project
+    let crates: NoHashHashMap<CrateId, CrateId> = project
         .crates()
         .filter_map(|(crate_id, krate)| {
             let file_path = &krate.root_module;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 07771d1b392..5392589186d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -22,7 +22,8 @@ anyhow = "1.0.57"
 crossbeam-channel = "0.5.5"
 dissimilar = "1.0.4"
 itertools = "0.10.3"
-lsp-types = { version = "0.93.0", features = ["proposed"] }
+scip = "0.1.1"
+lsp-types = { version = "0.93.1", features = ["proposed"] }
 parking_lot = "0.12.1"
 xflags = "0.2.4"
 oorandom = "11.1.3"
@@ -88,5 +89,5 @@ in-rust-tree = [
     "proc-macro-srv/sysroot-abi",
     "sourcegen/in-rust-tree",
     "ide/in-rust-tree",
-    "syntax/in-rust-tree"
+    "syntax/in-rust-tree",
 ]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index e9de23cb395..f6a68029725 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -93,6 +93,7 @@ fn try_main() -> Result<()> {
         flags::RustAnalyzerCmd::Ssr(cmd) => cmd.run()?,
         flags::RustAnalyzerCmd::Search(cmd) => cmd.run()?,
         flags::RustAnalyzerCmd::Lsif(cmd) => cmd.run()?,
+        flags::RustAnalyzerCmd::Scip(cmd) => cmd.run()?,
     }
     Ok(())
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs
index 6ccdaa86dd6..60ba67e25f9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs
@@ -9,6 +9,7 @@ mod analysis_stats;
 mod diagnostics;
 mod ssr;
 mod lsif;
+mod scip;
 
 mod progress_report;
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index 080e2fb4438..aa32654fbdc 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -112,6 +112,10 @@ xflags::xflags! {
         cmd lsif
             required path: PathBuf
         {}
+
+        cmd scip
+            required path: PathBuf
+        {}
     }
 }
 
@@ -140,6 +144,7 @@ pub enum RustAnalyzerCmd {
     Search(Search),
     ProcMacro(ProcMacro),
     Lsif(Lsif),
+    Scip(Scip),
 }
 
 #[derive(Debug)]
@@ -207,6 +212,11 @@ pub struct Lsif {
     pub path: PathBuf,
 }
 
+#[derive(Debug)]
+pub struct Scip {
+    pub path: PathBuf,
+}
+
 impl RustAnalyzer {
     pub const HELP: &'static str = Self::HELP_;
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
new file mode 100644
index 00000000000..65cc993c45e
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -0,0 +1,448 @@
+//! SCIP generator
+
+use std::{
+    collections::{HashMap, HashSet},
+    time::Instant,
+};
+
+use crate::line_index::{LineEndings, LineIndex, OffsetEncoding};
+use hir::Name;
+use ide::{
+    LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile, TextRange,
+    TokenId,
+};
+use ide_db::LineIndexDatabase;
+use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
+use scip::types as scip_types;
+use std::env;
+
+use crate::cli::{
+    flags,
+    load_cargo::{load_workspace, LoadCargoConfig},
+    Result,
+};
+
+impl flags::Scip {
+    pub fn run(self) -> Result<()> {
+        eprintln!("Generating SCIP start...");
+        let now = Instant::now();
+        let cargo_config = CargoConfig::default();
+
+        let no_progress = &|s| (eprintln!("rust-analyzer: Loading {}", s));
+        let load_cargo_config = LoadCargoConfig {
+            load_out_dirs_from_check: true,
+            with_proc_macro: true,
+            prefill_caches: true,
+        };
+        let path = vfs::AbsPathBuf::assert(env::current_dir()?.join(&self.path));
+        let rootpath = path.normalize();
+        let manifest = ProjectManifest::discover_single(&path)?;
+
+        let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
+
+        let (host, vfs, _) = load_workspace(workspace, &load_cargo_config)?;
+        let db = host.raw_database();
+        let analysis = host.analysis();
+
+        let si = StaticIndex::compute(&analysis);
+
+        let mut index = scip_types::Index {
+            metadata: Some(scip_types::Metadata {
+                version: scip_types::ProtocolVersion::UnspecifiedProtocolVersion.into(),
+                tool_info: Some(scip_types::ToolInfo {
+                    name: "rust-analyzer".to_owned(),
+                    version: "0.1".to_owned(),
+                    arguments: vec![],
+                    ..Default::default()
+                })
+                .into(),
+                project_root: format!(
+                    "file://{}",
+                    path.normalize()
+                        .as_os_str()
+                        .to_str()
+                        .ok_or(anyhow::anyhow!("Unable to normalize project_root path"))?
+                        .to_string()
+                ),
+                text_document_encoding: scip_types::TextEncoding::UTF8.into(),
+                ..Default::default()
+            })
+            .into(),
+            ..Default::default()
+        };
+
+        let mut symbols_emitted: HashSet<TokenId> = HashSet::default();
+        let mut tokens_to_symbol: HashMap<TokenId, String> = HashMap::new();
+
+        for file in si.files {
+            let mut local_count = 0;
+            let mut new_local_symbol = || {
+                let new_symbol = scip::types::Symbol::new_local(local_count);
+                local_count += 1;
+
+                new_symbol
+            };
+
+            let StaticIndexedFile { file_id, tokens, .. } = file;
+            let relative_path = match get_relative_filepath(&vfs, &rootpath, file_id) {
+                Some(relative_path) => relative_path,
+                None => continue,
+            };
+
+            let line_index = LineIndex {
+                index: db.line_index(file_id),
+                encoding: OffsetEncoding::Utf8,
+                endings: LineEndings::Unix,
+            };
+
+            let mut doc = scip_types::Document {
+                relative_path,
+                language: "rust".to_string(),
+                ..Default::default()
+            };
+
+            tokens.into_iter().for_each(|(range, id)| {
+                let token = si.tokens.get(id).unwrap();
+
+                let mut occurrence = scip_types::Occurrence::default();
+                occurrence.range = text_range_to_scip_range(&line_index, range);
+                occurrence.symbol = match tokens_to_symbol.get(&id) {
+                    Some(symbol) => symbol.clone(),
+                    None => {
+                        let symbol = match &token.moniker {
+                            Some(moniker) => moniker_to_symbol(&moniker),
+                            None => new_local_symbol(),
+                        };
+
+                        let symbol = scip::symbol::format_symbol(symbol);
+                        tokens_to_symbol.insert(id, symbol.clone());
+                        symbol
+                    }
+                };
+
+                if let Some(def) = token.definition {
+                    if def.range == range {
+                        occurrence.symbol_roles |= scip_types::SymbolRole::Definition as i32;
+                    }
+
+                    if !symbols_emitted.contains(&id) {
+                        symbols_emitted.insert(id);
+
+                        let mut symbol_info = scip_types::SymbolInformation::default();
+                        symbol_info.symbol = occurrence.symbol.clone();
+                        if let Some(hover) = &token.hover {
+                            if !hover.markup.as_str().is_empty() {
+                                symbol_info.documentation = vec![hover.markup.as_str().to_string()];
+                            }
+                        }
+
+                        doc.symbols.push(symbol_info)
+                    }
+                }
+
+                doc.occurrences.push(occurrence);
+            });
+
+            if doc.occurrences.is_empty() {
+                continue;
+            }
+
+            index.documents.push(doc);
+        }
+
+        scip::write_message_to_file("index.scip", index)
+            .map_err(|err| anyhow::anyhow!("Failed to write scip to file: {}", err))?;
+
+        eprintln!("Generating SCIP finished {:?}", now.elapsed());
+        Ok(())
+    }
+}
+
+fn get_relative_filepath(
+    vfs: &vfs::Vfs,
+    rootpath: &vfs::AbsPathBuf,
+    file_id: ide::FileId,
+) -> Option<String> {
+    Some(vfs.file_path(file_id).as_path()?.strip_prefix(&rootpath)?.as_ref().to_str()?.to_string())
+}
+
+// SCIP Ranges have a (very large) optimization that ranges if they are on the same line
+// only encode as a vector of [start_line, start_col, end_col].
+//
+// This transforms a line index into the optimized SCIP Range.
+fn text_range_to_scip_range(line_index: &LineIndex, range: TextRange) -> Vec<i32> {
+    let LineCol { line: start_line, col: start_col } = line_index.index.line_col(range.start());
+    let LineCol { line: end_line, col: end_col } = line_index.index.line_col(range.end());
+
+    if start_line == end_line {
+        vec![start_line as i32, start_col as i32, end_col as i32]
+    } else {
+        vec![start_line as i32, start_col as i32, end_line as i32, end_col as i32]
+    }
+}
+
+fn new_descriptor_str(
+    name: &str,
+    suffix: scip_types::descriptor::Suffix,
+) -> scip_types::Descriptor {
+    scip_types::Descriptor {
+        name: name.to_string(),
+        disambiguator: "".to_string(),
+        suffix: suffix.into(),
+        ..Default::default()
+    }
+}
+
+fn new_descriptor(name: Name, suffix: scip_types::descriptor::Suffix) -> scip_types::Descriptor {
+    let mut name = name.to_string();
+    if name.contains("'") {
+        name = format!("`{}`", name);
+    }
+
+    new_descriptor_str(name.as_str(), suffix)
+}
+
+/// Loosely based on `def_to_moniker`
+///
+/// Only returns a Symbol when it's a non-local symbol.
+///     So if the visibility isn't outside of a document, then it will return None
+fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
+    use scip_types::descriptor::Suffix::*;
+
+    let package_name = moniker.package_information.name.clone();
+    let version = moniker.package_information.version.clone();
+    let descriptors = moniker
+        .identifier
+        .description
+        .iter()
+        .map(|desc| {
+            new_descriptor(
+                desc.name.clone(),
+                match desc.desc {
+                    MonikerDescriptorKind::Namespace => Namespace,
+                    MonikerDescriptorKind::Type => Type,
+                    MonikerDescriptorKind::Term => Term,
+                    MonikerDescriptorKind::Method => Method,
+                    MonikerDescriptorKind::TypeParameter => TypeParameter,
+                    MonikerDescriptorKind::Parameter => Parameter,
+                    MonikerDescriptorKind::Macro => Macro,
+                    MonikerDescriptorKind::Meta => Meta,
+                },
+            )
+        })
+        .collect();
+
+    scip_types::Symbol {
+        scheme: "rust-analyzer".into(),
+        package: Some(scip_types::Package {
+            manager: "cargo".to_string(),
+            name: package_name,
+            version,
+            ..Default::default()
+        })
+        .into(),
+        descriptors,
+        ..Default::default()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use hir::Semantics;
+    use ide::{AnalysisHost, FilePosition};
+    use ide_db::defs::IdentClass;
+    use ide_db::{base_db::fixture::ChangeFixture, helpers::pick_best_token};
+    use scip::symbol::format_symbol;
+    use syntax::SyntaxKind::*;
+    use syntax::{AstNode, T};
+
+    fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) {
+        let mut host = AnalysisHost::default();
+        let change_fixture = ChangeFixture::parse(ra_fixture);
+        host.raw_database_mut().apply_change(change_fixture.change);
+        let (file_id, range_or_offset) =
+            change_fixture.file_position.expect("expected a marker ($0)");
+        let offset = range_or_offset.expect_offset();
+        (host, FilePosition { file_id, offset })
+    }
+
+    /// If expected == "", then assert that there are no symbols (this is basically local symbol)
+    #[track_caller]
+    fn check_symbol(ra_fixture: &str, expected: &str) {
+        let (host, position) = position(ra_fixture);
+
+        let FilePosition { file_id, offset } = position;
+
+        let db = host.raw_database();
+        let sema = &Semantics::new(db);
+        let file = sema.parse(file_id).syntax().clone();
+        let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
+            IDENT
+            | INT_NUMBER
+            | LIFETIME_IDENT
+            | T![self]
+            | T![super]
+            | T![crate]
+            | T![Self]
+            | COMMENT => 2,
+            kind if kind.is_trivia() => 0,
+            _ => 1,
+        })
+        .expect("OK OK");
+
+        let navs = sema
+            .descend_into_macros(original_token.clone())
+            .into_iter()
+            .filter_map(|token| {
+                IdentClass::classify_token(sema, &token).map(IdentClass::definitions).map(|it| {
+                    it.into_iter().flat_map(|def| {
+                        let module = def.module(db).unwrap();
+                        let current_crate = module.krate();
+
+                        match MonikerResult::from_def(sema.db, def, current_crate) {
+                            Some(moniker_result) => Some(moniker_to_symbol(&moniker_result)),
+                            None => None,
+                        }
+                    })
+                })
+            })
+            .flatten()
+            .collect::<Vec<_>>();
+
+        if expected == "" {
+            assert_eq!(0, navs.len(), "must have no symbols {:?}", navs);
+            return;
+        }
+
+        assert_eq!(1, navs.len(), "must have one symbol {:?}", navs);
+
+        let res = navs.get(0).unwrap();
+        let formatted = format_symbol(res.clone());
+        assert_eq!(formatted, expected);
+    }
+
+    #[test]
+    fn basic() {
+        check_symbol(
+            r#"
+//- /lib.rs crate:main deps:foo
+use foo::example_mod::func;
+fn main() {
+    func$0();
+}
+//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+pub mod example_mod {
+    pub fn func() {}
+}
+"#,
+            "rust-analyzer cargo foo 0.1.0 example_mod/func().",
+        );
+    }
+
+    #[test]
+    fn symbol_for_trait() {
+        check_symbol(
+            r#"
+//- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+pub mod module {
+    pub trait MyTrait {
+        pub fn func$0() {}
+    }
+}
+"#,
+            "rust-analyzer cargo foo 0.1.0 module/MyTrait#func().",
+        );
+    }
+
+    #[test]
+    fn symbol_for_trait_constant() {
+        check_symbol(
+            r#"
+    //- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+    pub mod module {
+        pub trait MyTrait {
+            const MY_CONST$0: u8;
+        }
+    }
+    "#,
+            "rust-analyzer cargo foo 0.1.0 module/MyTrait#MY_CONST.",
+        );
+    }
+
+    #[test]
+    fn symbol_for_trait_type() {
+        check_symbol(
+            r#"
+    //- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+    pub mod module {
+        pub trait MyTrait {
+            type MyType$0;
+        }
+    }
+    "#,
+            // "foo::module::MyTrait::MyType",
+            "rust-analyzer cargo foo 0.1.0 module/MyTrait#[MyType]",
+        );
+    }
+
+    #[test]
+    fn symbol_for_trait_impl_function() {
+        check_symbol(
+            r#"
+    //- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+    pub mod module {
+        pub trait MyTrait {
+            pub fn func() {}
+        }
+
+        struct MyStruct {}
+
+        impl MyTrait for MyStruct {
+            pub fn func$0() {}
+        }
+    }
+    "#,
+            // "foo::module::MyStruct::MyTrait::func",
+            "rust-analyzer cargo foo 0.1.0 module/MyStruct#MyTrait#func().",
+        );
+    }
+
+    #[test]
+    fn symbol_for_field() {
+        check_symbol(
+            r#"
+    //- /lib.rs crate:main deps:foo
+    use foo::St;
+    fn main() {
+        let x = St { a$0: 2 };
+    }
+    //- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+    pub struct St {
+        pub a: i32,
+    }
+    "#,
+            "rust-analyzer cargo foo 0.1.0 St#a.",
+        );
+    }
+
+    #[test]
+    fn local_symbol_for_local() {
+        check_symbol(
+            r#"
+    //- /lib.rs crate:main deps:foo
+    use foo::module::func;
+    fn main() {
+        func();
+    }
+    //- /foo/lib.rs crate:foo@CratesIo:0.1.0,https://a.b/foo.git
+    pub mod module {
+        pub fn func() {
+            let x$0 = 2;
+        }
+    }
+    "#,
+            "",
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 6649f42b4ef..54dcb42d99c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -12,8 +12,8 @@ use std::{ffi::OsString, fmt, iter, path::PathBuf};
 use flycheck::FlycheckConfig;
 use ide::{
     AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
-    HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayHintsConfig, JoinLinesConfig,
-    Snippet, SnippetScope,
+    HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayHintsConfig,
+    JoinLinesConfig, Snippet, SnippetScope,
 };
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
@@ -385,6 +385,34 @@ config_data! {
         /// available on a nightly build.
         rustfmt_rangeFormatting_enable: bool = "false",
 
+        /// Inject additional highlighting into doc comments.
+        ///
+        /// When enabled, rust-analyzer will highlight rust source in doc comments as well as intra
+        /// doc links.
+        semanticHighlighting_doc_comment_inject_enable: bool = "true",
+        /// Use semantic tokens for operators.
+        ///
+        /// When disabled, rust-analyzer will emit semantic tokens only for operator tokens when
+        /// they are tagged with modifiers.
+        semanticHighlighting_operator_enable: bool = "true",
+        /// Use specialized semantic tokens for operators.
+        ///
+        /// When enabled, rust-analyzer will emit special token types for operator tokens instead
+        /// of the generic `operator` token type.
+        semanticHighlighting_operator_specialization_enable: bool = "false",
+        /// Use semantic tokens for punctuations.
+        ///
+        /// When disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when
+        /// they are tagged with modifiers or have a special role.
+        semanticHighlighting_punctuation_enable: bool = "false",
+        /// When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro
+        /// calls.
+        semanticHighlighting_punctuation_separate_macro_bang: bool = "false",
+        /// Use specialized semantic tokens for punctuations.
+        ///
+        /// When enabled, rust-analyzer will emit special token types for punctuation tokens instead
+        /// of the generic `punctuation` token type.
+        semanticHighlighting_punctuation_specialization_enable: bool = "false",
         /// Use semantic tokens for strings.
         ///
         /// In some editors (e.g. vscode) semantic tokens override other highlighting grammars.
@@ -1171,8 +1199,19 @@ impl Config {
         }
     }
 
-    pub fn highlighting_strings(&self) -> bool {
-        self.data.semanticHighlighting_strings_enable
+    pub fn highlighting_config(&self) -> HighlightConfig {
+        HighlightConfig {
+            strings: self.data.semanticHighlighting_strings_enable,
+            punctuation: self.data.semanticHighlighting_punctuation_enable,
+            specialize_punctuation: self
+                .data
+                .semanticHighlighting_punctuation_specialization_enable,
+            macro_bang: self.data.semanticHighlighting_punctuation_separate_macro_bang,
+            operator: self.data.semanticHighlighting_operator_enable,
+            specialize_operator: self.data.semanticHighlighting_operator_specialization_enable,
+            inject_doc_comment: self.data.semanticHighlighting_doc_comment_inject_enable,
+            syntactic_name_ref_highlighting: false,
+        }
     }
 
     pub fn hover(&self) -> HoverConfig {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
index 09150c77d7d..f516c194da4 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
@@ -4,11 +4,12 @@ pub(crate) mod to_proto;
 use std::{mem, sync::Arc};
 
 use ide::FileId;
-use rustc_hash::{FxHashMap, FxHashSet};
+use ide_db::FxHashMap;
+use stdx::hash::{NoHashHashMap, NoHashHashSet};
 
 use crate::lsp_ext;
 
-pub(crate) type CheckFixes = Arc<FxHashMap<usize, FxHashMap<FileId, Vec<Fix>>>>;
+pub(crate) type CheckFixes = Arc<NoHashHashMap<usize, NoHashHashMap<FileId, Vec<Fix>>>>;
 
 #[derive(Debug, Default, Clone)]
 pub struct DiagnosticsMapConfig {
@@ -19,12 +20,12 @@ pub struct DiagnosticsMapConfig {
 
 #[derive(Debug, Default, Clone)]
 pub(crate) struct DiagnosticCollection {
-    // FIXME: should be FxHashMap<FileId, Vec<ra_id::Diagnostic>>
-    pub(crate) native: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
+    // FIXME: should be NoHashHashMap<FileId, Vec<ra_id::Diagnostic>>
+    pub(crate) native: NoHashHashMap<FileId, Vec<lsp_types::Diagnostic>>,
     // FIXME: should be Vec<flycheck::Diagnostic>
-    pub(crate) check: FxHashMap<usize, FxHashMap<FileId, Vec<lsp_types::Diagnostic>>>,
+    pub(crate) check: NoHashHashMap<usize, NoHashHashMap<FileId, Vec<lsp_types::Diagnostic>>>,
     pub(crate) check_fixes: CheckFixes,
-    changes: FxHashSet<FileId>,
+    changes: NoHashHashSet<FileId>,
 }
 
 #[derive(Debug, Clone)]
@@ -105,7 +106,7 @@ impl DiagnosticCollection {
         native.chain(check)
     }
 
-    pub(crate) fn take_changes(&mut self) -> Option<FxHashSet<FileId>> {
+    pub(crate) fn take_changes(&mut self) -> Option<NoHashHashSet<FileId>> {
         if self.changes.is_empty() {
             return None;
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index c55bbbbe6ef..706e1742dff 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -14,6 +14,7 @@ use parking_lot::{Mutex, RwLock};
 use proc_macro_api::ProcMacroServer;
 use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
 use rustc_hash::FxHashMap;
+use stdx::hash::NoHashHashMap;
 use vfs::AnchoredPathBuf;
 
 use crate::{
@@ -67,7 +68,7 @@ pub(crate) struct GlobalState {
     pub(crate) flycheck_sender: Sender<flycheck::Message>,
     pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
 
-    pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
+    pub(crate) vfs: Arc<RwLock<(vfs::Vfs, NoHashHashMap<FileId, LineEndings>)>>,
     pub(crate) vfs_config_version: u32,
     pub(crate) vfs_progress_config_version: u32,
     pub(crate) vfs_progress_n_total: usize,
@@ -113,7 +114,7 @@ pub(crate) struct GlobalStateSnapshot {
     pub(crate) check_fixes: CheckFixes,
     mem_docs: MemDocs,
     pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
-    vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
+    vfs: Arc<RwLock<(vfs::Vfs, NoHashHashMap<FileId, LineEndings>)>>,
     pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
 }
 
@@ -157,7 +158,7 @@ impl GlobalState {
             flycheck_sender,
             flycheck_receiver,
 
-            vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
+            vfs: Arc::new(RwLock::new((vfs::Vfs::default(), NoHashHashMap::default()))),
             vfs_config_version: 0,
             vfs_progress_config_version: 0,
             vfs_progress_n_total: 0,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
index e0bcc80b31c..d89f0f5a3cf 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
@@ -1504,10 +1504,8 @@ pub(crate) fn handle_semantic_tokens_full(
     let text = snap.analysis.file_text(file_id)?;
     let line_index = snap.file_line_index(file_id)?;
 
-    let highlights = snap.analysis.highlight(file_id)?;
-    let highlight_strings = snap.config.highlighting_strings();
-    let semantic_tokens =
-        to_proto::semantic_tokens(&text, &line_index, highlights, highlight_strings);
+    let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?;
+    let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
 
     // Unconditionally cache the tokens
     snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens.clone());
@@ -1525,10 +1523,8 @@ pub(crate) fn handle_semantic_tokens_full_delta(
     let text = snap.analysis.file_text(file_id)?;
     let line_index = snap.file_line_index(file_id)?;
 
-    let highlights = snap.analysis.highlight(file_id)?;
-    let highlight_strings = snap.config.highlighting_strings();
-    let semantic_tokens =
-        to_proto::semantic_tokens(&text, &line_index, highlights, highlight_strings);
+    let highlights = snap.analysis.highlight(snap.config.highlighting_config(), file_id)?;
+    let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
 
     let mut cache = snap.semantic_tokens_cache.lock();
     let cached_tokens = cache.entry(params.text_document.uri).or_default();
@@ -1556,10 +1552,8 @@ pub(crate) fn handle_semantic_tokens_range(
     let text = snap.analysis.file_text(frange.file_id)?;
     let line_index = snap.file_line_index(frange.file_id)?;
 
-    let highlights = snap.analysis.highlight_range(frange)?;
-    let highlight_strings = snap.config.highlighting_strings();
-    let semantic_tokens =
-        to_proto::semantic_tokens(&text, &line_index, highlights, highlight_strings);
+    let highlights = snap.analysis.highlight_range(snap.config.highlighting_config(), frange)?;
+    let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
     Ok(Some(semantic_tokens.into()))
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index f187547019a..3cfbc2e4e45 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -328,8 +328,33 @@ impl GlobalState {
                 }
 
                 let uri = file_id_to_url(&self.vfs.read().0, file_id);
-                let diagnostics =
+                let mut diagnostics =
                     self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
+
+                // VSCode assumes diagnostic messages to be non-empty strings, so we need to patch
+                // empty diagnostics. Neither the docs of VSCode nor the LSP spec say whether
+                // diagnostic messages are actually allowed to be empty or not and patching this
+                // in the VSCode client does not work as the assertion happens in the protocol
+                // conversion. So this hack is here to stay, and will be considered a hack
+                // until the LSP decides to state that empty messages are allowed.
+
+                // See https://github.com/rust-lang/rust-analyzer/issues/11404
+                // See https://github.com/rust-lang/rust-analyzer/issues/13130
+                let patch_empty = |message: &mut String| {
+                    if message.is_empty() {
+                        *message = " ".to_string();
+                    }
+                };
+
+                for d in &mut diagnostics {
+                    patch_empty(&mut d.message);
+                    if let Some(dri) = &mut d.related_information {
+                        for dri in dri {
+                            patch_empty(&mut dri.message);
+                        }
+                    }
+                }
+
                 let version = from_proto::vfs_path(&uri)
                     .map(|path| self.mem_docs.get(&path).map(|it| it.version))
                     .unwrap_or_default();
@@ -529,6 +554,13 @@ impl GlobalState {
                     }
                     flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
                     flycheck::Progress::DidCancel => (Progress::End, None),
+                    flycheck::Progress::DidFailToRestart(err) => {
+                        self.show_and_log_error(
+                            "cargo check failed".to_string(),
+                            Some(err.to_string()),
+                        );
+                        return;
+                    }
                     flycheck::Progress::DidFinish(result) => {
                         if let Err(err) = result {
                             self.show_and_log_error(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
index 6c78b5df1a7..c48410ed55e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
@@ -8,107 +8,130 @@ use lsp_types::{
 };
 
 macro_rules! define_semantic_token_types {
-    ($(($ident:ident, $string:literal)),*$(,)?) => {
-        $(pub(crate) const $ident: SemanticTokenType = SemanticTokenType::new($string);)*
+    (
+        standard {
+            $($standard:ident),*$(,)?
+        }
+        custom {
+            $(($custom:ident, $string:literal)),*$(,)?
+        }
+
+    ) => {
+        $(pub(crate) const $standard: SemanticTokenType = SemanticTokenType::$standard;)*
+        $(pub(crate) const $custom: SemanticTokenType = SemanticTokenType::new($string);)*
 
         pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
-            SemanticTokenType::COMMENT,
-            SemanticTokenType::KEYWORD,
-            SemanticTokenType::STRING,
-            SemanticTokenType::NUMBER,
-            SemanticTokenType::REGEXP,
-            SemanticTokenType::OPERATOR,
-            SemanticTokenType::NAMESPACE,
-            SemanticTokenType::TYPE,
-            SemanticTokenType::STRUCT,
-            SemanticTokenType::CLASS,
-            SemanticTokenType::INTERFACE,
-            SemanticTokenType::ENUM,
-            SemanticTokenType::ENUM_MEMBER,
-            SemanticTokenType::TYPE_PARAMETER,
-            SemanticTokenType::FUNCTION,
-            SemanticTokenType::METHOD,
-            SemanticTokenType::PROPERTY,
-            SemanticTokenType::MACRO,
-            SemanticTokenType::VARIABLE,
-            SemanticTokenType::PARAMETER,
-            $($ident),*
+            $(SemanticTokenType::$standard,)*
+            $($custom),*
         ];
     };
 }
 
 define_semantic_token_types![
-    (ANGLE, "angle"),
-    (ARITHMETIC, "arithmetic"),
-    (ATTRIBUTE, "attribute"),
-    (ATTRIBUTE_BRACKET, "attributeBracket"),
-    (BITWISE, "bitwise"),
-    (BOOLEAN, "boolean"),
-    (BRACE, "brace"),
-    (BRACKET, "bracket"),
-    (BUILTIN_ATTRIBUTE, "builtinAttribute"),
-    (BUILTIN_TYPE, "builtinType"),
-    (CHAR, "character"),
-    (COLON, "colon"),
-    (COMMA, "comma"),
-    (COMPARISON, "comparison"),
-    (CONST_PARAMETER, "constParameter"),
-    (DERIVE, "derive"),
-    (DERIVE_HELPER, "deriveHelper"),
-    (DOT, "dot"),
-    (ESCAPE_SEQUENCE, "escapeSequence"),
-    (FORMAT_SPECIFIER, "formatSpecifier"),
-    (GENERIC, "generic"),
-    (LABEL, "label"),
-    (LIFETIME, "lifetime"),
-    (LOGICAL, "logical"),
-    (MACRO_BANG, "macroBang"),
-    (OPERATOR, "operator"),
-    (PARENTHESIS, "parenthesis"),
-    (PUNCTUATION, "punctuation"),
-    (SELF_KEYWORD, "selfKeyword"),
-    (SELF_TYPE_KEYWORD, "selfTypeKeyword"),
-    (SEMICOLON, "semicolon"),
-    (TYPE_ALIAS, "typeAlias"),
-    (TOOL_MODULE, "toolModule"),
-    (UNION, "union"),
-    (UNRESOLVED_REFERENCE, "unresolvedReference"),
+    standard {
+        COMMENT,
+        DECORATOR,
+        ENUM_MEMBER,
+        ENUM,
+        FUNCTION,
+        INTERFACE,
+        KEYWORD,
+        MACRO,
+        METHOD,
+        NAMESPACE,
+        NUMBER,
+        OPERATOR,
+        PARAMETER,
+        PROPERTY,
+        STRING,
+        STRUCT,
+        TYPE_PARAMETER,
+        VARIABLE,
+    }
+
+    custom {
+        (ANGLE, "angle"),
+        (ARITHMETIC, "arithmetic"),
+        (ATTRIBUTE, "attribute"),
+        (ATTRIBUTE_BRACKET, "attributeBracket"),
+        (BITWISE, "bitwise"),
+        (BOOLEAN, "boolean"),
+        (BRACE, "brace"),
+        (BRACKET, "bracket"),
+        (BUILTIN_ATTRIBUTE, "builtinAttribute"),
+        (BUILTIN_TYPE, "builtinType"),
+        (CHAR, "character"),
+        (COLON, "colon"),
+        (COMMA, "comma"),
+        (COMPARISON, "comparison"),
+        (CONST_PARAMETER, "constParameter"),
+        (DERIVE, "derive"),
+        (DERIVE_HELPER, "deriveHelper"),
+        (DOT, "dot"),
+        (ESCAPE_SEQUENCE, "escapeSequence"),
+        (FORMAT_SPECIFIER, "formatSpecifier"),
+        (GENERIC, "generic"),
+        (LABEL, "label"),
+        (LIFETIME, "lifetime"),
+        (LOGICAL, "logical"),
+        (MACRO_BANG, "macroBang"),
+        (PARENTHESIS, "parenthesis"),
+        (PUNCTUATION, "punctuation"),
+        (SELF_KEYWORD, "selfKeyword"),
+        (SELF_TYPE_KEYWORD, "selfTypeKeyword"),
+        (SEMICOLON, "semicolon"),
+        (TYPE_ALIAS, "typeAlias"),
+        (TOOL_MODULE, "toolModule"),
+        (UNION, "union"),
+        (UNRESOLVED_REFERENCE, "unresolvedReference"),
+    }
 ];
 
 macro_rules! define_semantic_token_modifiers {
-    ($(($ident:ident, $string:literal)),*$(,)?) => {
-        $(pub(crate) const $ident: SemanticTokenModifier = SemanticTokenModifier::new($string);)*
+    (
+        standard {
+            $($standard:ident),*$(,)?
+        }
+        custom {
+            $(($custom:ident, $string:literal)),*$(,)?
+        }
+
+    ) => {
+
+        $(pub(crate) const $standard: SemanticTokenModifier = SemanticTokenModifier::$standard;)*
+        $(pub(crate) const $custom: SemanticTokenModifier = SemanticTokenModifier::new($string);)*
 
         pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
-            SemanticTokenModifier::DOCUMENTATION,
-            SemanticTokenModifier::DECLARATION,
-            SemanticTokenModifier::DEFINITION,
-            SemanticTokenModifier::STATIC,
-            SemanticTokenModifier::ABSTRACT,
-            SemanticTokenModifier::DEPRECATED,
-            SemanticTokenModifier::READONLY,
-            SemanticTokenModifier::DEFAULT_LIBRARY,
-            $($ident),*
+            $(SemanticTokenModifier::$standard,)*
+            $($custom),*
         ];
     };
 }
 
 define_semantic_token_modifiers![
-    (ASYNC, "async"),
-    (ATTRIBUTE_MODIFIER, "attribute"),
-    (CALLABLE, "callable"),
-    (CONSTANT, "constant"),
-    (CONSUMING, "consuming"),
-    (CONTROL_FLOW, "controlFlow"),
-    (CRATE_ROOT, "crateRoot"),
-    (INJECTED, "injected"),
-    (INTRA_DOC_LINK, "intraDocLink"),
-    (LIBRARY, "library"),
-    (MUTABLE, "mutable"),
-    (PUBLIC, "public"),
-    (REFERENCE, "reference"),
-    (TRAIT_MODIFIER, "trait"),
-    (UNSAFE, "unsafe"),
+    standard {
+        DOCUMENTATION,
+        DECLARATION,
+        STATIC,
+        DEFAULT_LIBRARY,
+    }
+    custom {
+        (ASYNC, "async"),
+        (ATTRIBUTE_MODIFIER, "attribute"),
+        (CALLABLE, "callable"),
+        (CONSTANT, "constant"),
+        (CONSUMING, "consuming"),
+        (CONTROL_FLOW, "controlFlow"),
+        (CRATE_ROOT, "crateRoot"),
+        (INJECTED, "injected"),
+        (INTRA_DOC_LINK, "intraDocLink"),
+        (LIBRARY, "library"),
+        (MUTABLE, "mutable"),
+        (PUBLIC, "public"),
+        (REFERENCE, "reference"),
+        (TRAIT_MODIFIER, "trait"),
+        (UNSAFE, "unsafe"),
+    }
 ];
 
 #[derive(Default)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
index e7115b0732e..102cd602950 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
@@ -517,7 +517,6 @@ pub(crate) fn semantic_tokens(
     text: &str,
     line_index: &LineIndex,
     highlights: Vec<HlRange>,
-    highlight_strings: bool,
 ) -> lsp_types::SemanticTokens {
     let id = TOKEN_RESULT_COUNTER.fetch_add(1, Ordering::SeqCst).to_string();
     let mut builder = semantic_tokens::SemanticTokensBuilder::new(id);
@@ -526,10 +525,8 @@ pub(crate) fn semantic_tokens(
         if highlight_range.highlight.is_empty() {
             continue;
         }
+
         let (ty, mods) = semantic_token_type_and_modifiers(highlight_range.highlight);
-        if !highlight_strings && ty == lsp_types::SemanticTokenType::STRING {
-            continue;
-        }
         let token_index = semantic_tokens::type_index(ty);
         let modifier_bitset = mods.0;
 
@@ -561,55 +558,55 @@ fn semantic_token_type_and_modifiers(
     let mut mods = semantic_tokens::ModifierSet::default();
     let type_ = match highlight.tag {
         HlTag::Symbol(symbol) => match symbol {
-            SymbolKind::Attribute => semantic_tokens::ATTRIBUTE,
+            SymbolKind::Attribute => semantic_tokens::DECORATOR,
             SymbolKind::Derive => semantic_tokens::DERIVE,
             SymbolKind::DeriveHelper => semantic_tokens::DERIVE_HELPER,
-            SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
+            SymbolKind::Module => semantic_tokens::NAMESPACE,
             SymbolKind::Impl => semantic_tokens::TYPE_ALIAS,
-            SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
-            SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
+            SymbolKind::Field => semantic_tokens::PROPERTY,
+            SymbolKind::TypeParam => semantic_tokens::TYPE_PARAMETER,
             SymbolKind::ConstParam => semantic_tokens::CONST_PARAMETER,
             SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
             SymbolKind::Label => semantic_tokens::LABEL,
-            SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
+            SymbolKind::ValueParam => semantic_tokens::PARAMETER,
             SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD,
             SymbolKind::SelfType => semantic_tokens::SELF_TYPE_KEYWORD,
-            SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE,
+            SymbolKind::Local => semantic_tokens::VARIABLE,
             SymbolKind::Function => {
                 if highlight.mods.contains(HlMod::Associated) {
-                    lsp_types::SemanticTokenType::METHOD
+                    semantic_tokens::METHOD
                 } else {
-                    lsp_types::SemanticTokenType::FUNCTION
+                    semantic_tokens::FUNCTION
                 }
             }
             SymbolKind::Const => {
                 mods |= semantic_tokens::CONSTANT;
-                mods |= lsp_types::SemanticTokenModifier::STATIC;
-                lsp_types::SemanticTokenType::VARIABLE
+                mods |= semantic_tokens::STATIC;
+                semantic_tokens::VARIABLE
             }
             SymbolKind::Static => {
-                mods |= lsp_types::SemanticTokenModifier::STATIC;
-                lsp_types::SemanticTokenType::VARIABLE
+                mods |= semantic_tokens::STATIC;
+                semantic_tokens::VARIABLE
             }
-            SymbolKind::Struct => lsp_types::SemanticTokenType::STRUCT,
-            SymbolKind::Enum => lsp_types::SemanticTokenType::ENUM,
-            SymbolKind::Variant => lsp_types::SemanticTokenType::ENUM_MEMBER,
+            SymbolKind::Struct => semantic_tokens::STRUCT,
+            SymbolKind::Enum => semantic_tokens::ENUM,
+            SymbolKind::Variant => semantic_tokens::ENUM_MEMBER,
             SymbolKind::Union => semantic_tokens::UNION,
             SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS,
-            SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE,
-            SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO,
+            SymbolKind::Trait => semantic_tokens::INTERFACE,
+            SymbolKind::Macro => semantic_tokens::MACRO,
             SymbolKind::BuiltinAttr => semantic_tokens::BUILTIN_ATTRIBUTE,
             SymbolKind::ToolModule => semantic_tokens::TOOL_MODULE,
         },
         HlTag::AttributeBracket => semantic_tokens::ATTRIBUTE_BRACKET,
         HlTag::BoolLiteral => semantic_tokens::BOOLEAN,
         HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
-        HlTag::ByteLiteral | HlTag::NumericLiteral => lsp_types::SemanticTokenType::NUMBER,
+        HlTag::ByteLiteral | HlTag::NumericLiteral => semantic_tokens::NUMBER,
         HlTag::CharLiteral => semantic_tokens::CHAR,
-        HlTag::Comment => lsp_types::SemanticTokenType::COMMENT,
+        HlTag::Comment => semantic_tokens::COMMENT,
         HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
         HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
-        HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD,
+        HlTag::Keyword => semantic_tokens::KEYWORD,
         HlTag::None => semantic_tokens::GENERIC,
         HlTag::Operator(op) => match op {
             HlOperator::Bitwise => semantic_tokens::BITWISE,
@@ -618,7 +615,7 @@ fn semantic_token_type_and_modifiers(
             HlOperator::Comparison => semantic_tokens::COMPARISON,
             HlOperator::Other => semantic_tokens::OPERATOR,
         },
-        HlTag::StringLiteral => lsp_types::SemanticTokenType::STRING,
+        HlTag::StringLiteral => semantic_tokens::STRING,
         HlTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE,
         HlTag::Punctuation(punct) => match punct {
             HlPunct::Bracket => semantic_tokens::BRACKET,
@@ -643,16 +640,16 @@ fn semantic_token_type_and_modifiers(
             HlMod::Consuming => semantic_tokens::CONSUMING,
             HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW,
             HlMod::CrateRoot => semantic_tokens::CRATE_ROOT,
-            HlMod::DefaultLibrary => lsp_types::SemanticTokenModifier::DEFAULT_LIBRARY,
-            HlMod::Definition => lsp_types::SemanticTokenModifier::DECLARATION,
-            HlMod::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION,
+            HlMod::DefaultLibrary => semantic_tokens::DEFAULT_LIBRARY,
+            HlMod::Definition => semantic_tokens::DECLARATION,
+            HlMod::Documentation => semantic_tokens::DOCUMENTATION,
             HlMod::Injected => semantic_tokens::INJECTED,
             HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
             HlMod::Library => semantic_tokens::LIBRARY,
             HlMod::Mutable => semantic_tokens::MUTABLE,
             HlMod::Public => semantic_tokens::PUBLIC,
             HlMod::Reference => semantic_tokens::REFERENCE,
-            HlMod::Static => lsp_types::SemanticTokenModifier::STATIC,
+            HlMod::Static => semantic_tokens::STATIC,
             HlMod::Trait => semantic_tokens::TRAIT_MODIFIER,
             HlMod::Unsafe => semantic_tokens::UNSAFE,
         };
diff --git a/src/tools/rust-analyzer/crates/stdx/src/hash.rs b/src/tools/rust-analyzer/crates/stdx/src/hash.rs
new file mode 100644
index 00000000000..9909d71bdf0
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/stdx/src/hash.rs
@@ -0,0 +1,80 @@
+//! A none hashing [`Hasher`] implementation.
+use std::{
+    hash::{BuildHasher, Hasher},
+    marker::PhantomData,
+};
+
+pub type NoHashHashMap<K, V> = std::collections::HashMap<K, V, NoHashHasherBuilder<K>>;
+pub type NoHashHashSet<K> = std::collections::HashSet<K, NoHashHasherBuilder<K>>;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct NoHashHasherBuilder<T>(PhantomData<T>);
+
+impl<T> Default for NoHashHasherBuilder<T> {
+    fn default() -> Self {
+        Self(Default::default())
+    }
+}
+
+pub trait NoHashHashable {}
+impl NoHashHashable for usize {}
+impl NoHashHashable for u32 {}
+
+pub struct NoHashHasher(u64);
+
+impl<T: NoHashHashable> BuildHasher for NoHashHasherBuilder<T> {
+    type Hasher = NoHashHasher;
+    fn build_hasher(&self) -> Self::Hasher {
+        NoHashHasher(0)
+    }
+}
+
+impl Hasher for NoHashHasher {
+    fn finish(&self) -> u64 {
+        self.0
+    }
+
+    fn write(&mut self, _: &[u8]) {
+        unimplemented!("NoHashHasher should only be used for hashing primitive integers")
+    }
+
+    fn write_u8(&mut self, i: u8) {
+        self.0 = i as u64;
+    }
+
+    fn write_u16(&mut self, i: u16) {
+        self.0 = i as u64;
+    }
+
+    fn write_u32(&mut self, i: u32) {
+        self.0 = i as u64;
+    }
+
+    fn write_u64(&mut self, i: u64) {
+        self.0 = i as u64;
+    }
+
+    fn write_usize(&mut self, i: usize) {
+        self.0 = i as u64;
+    }
+
+    fn write_i8(&mut self, i: i8) {
+        self.0 = i as u64;
+    }
+
+    fn write_i16(&mut self, i: i16) {
+        self.0 = i as u64;
+    }
+
+    fn write_i32(&mut self, i: i32) {
+        self.0 = i as u64;
+    }
+
+    fn write_i64(&mut self, i: i64) {
+        self.0 = i as u64;
+    }
+
+    fn write_isize(&mut self, i: isize) {
+        self.0 = i as u64;
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
index b4d45206c44..51e109798d1 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
@@ -7,6 +7,7 @@ use std::{cmp::Ordering, ops, time::Instant};
 use std::{io as sio, iter};
 
 mod macros;
+pub mod hash;
 pub mod process;
 pub mod panic_context;
 pub mod non_empty_vec;
diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
index c6377348784..d7549a28415 100644
--- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
@@ -12,6 +12,7 @@ doctest = false
 [dependencies]
 rustc-hash = "1.1.0"
 fst = "0.4.7"
+indexmap = "1.9.1"
 
 paths = { path = "../paths", version = "0.0.0" }
-indexmap = "1.9.1"
+stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
index 6a89263e539..e0ef737b3fc 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
@@ -6,6 +6,7 @@ use std::fmt;
 
 use fst::{IntoStreamer, Streamer};
 use rustc_hash::FxHashMap;
+use stdx::hash::NoHashHashMap;
 
 use crate::{AnchoredPath, FileId, Vfs, VfsPath};
 
@@ -13,7 +14,7 @@ use crate::{AnchoredPath, FileId, Vfs, VfsPath};
 #[derive(Default, Clone, Eq, PartialEq)]
 pub struct FileSet {
     files: FxHashMap<VfsPath, FileId>,
-    paths: FxHashMap<FileId, VfsPath>,
+    paths: NoHashHashMap<FileId, VfsPath>,
 }
 
 impl FileSet {
diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
index 7badb1c363b..afc9a0fa6fb 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
@@ -59,9 +59,16 @@ pub use paths::{AbsPath, AbsPathBuf};
 /// Handle to a file in [`Vfs`]
 ///
 /// Most functions in rust-analyzer use this when they need to refer to a file.
-#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
 pub struct FileId(pub u32);
 
+impl stdx::hash::NoHashHashable for FileId {}
+impl std::hash::Hash for FileId {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
 /// Storage for all files read by rust-analyzer.
 ///
 /// For more information see the [crate-level](crate) documentation.
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 751ec79af0f..72b92572647 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -587,6 +587,52 @@ Enables the use of rustfmt's unstable range formatting command for the
 `textDocument/rangeFormatting` request. The rustfmt option is unstable and only
 available on a nightly build.
 --
+[[rust-analyzer.semanticHighlighting.doc.comment.inject.enable]]rust-analyzer.semanticHighlighting.doc.comment.inject.enable (default: `true`)::
++
+--
+Inject additional highlighting into doc comments.
+
+When enabled, rust-analyzer will highlight rust source in doc comments as well as intra
+doc links.
+--
+[[rust-analyzer.semanticHighlighting.operator.enable]]rust-analyzer.semanticHighlighting.operator.enable (default: `true`)::
++
+--
+Use semantic tokens for operators.
+
+When disabled, rust-analyzer will emit semantic tokens only for operator tokens when
+they are tagged with modifiers.
+--
+[[rust-analyzer.semanticHighlighting.operator.specialization.enable]]rust-analyzer.semanticHighlighting.operator.specialization.enable (default: `false`)::
++
+--
+Use specialized semantic tokens for operators.
+
+When enabled, rust-analyzer will emit special token types for operator tokens instead
+of the generic `operator` token type.
+--
+[[rust-analyzer.semanticHighlighting.punctuation.enable]]rust-analyzer.semanticHighlighting.punctuation.enable (default: `false`)::
++
+--
+Use semantic tokens for punctuations.
+
+When disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when
+they are tagged with modifiers or have a special role.
+--
+[[rust-analyzer.semanticHighlighting.punctuation.separate.macro.bang]]rust-analyzer.semanticHighlighting.punctuation.separate.macro.bang (default: `false`)::
++
+--
+When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro
+calls.
+--
+[[rust-analyzer.semanticHighlighting.punctuation.specialization.enable]]rust-analyzer.semanticHighlighting.punctuation.specialization.enable (default: `false`)::
++
+--
+Use specialized semantic tokens for punctuations.
+
+When enabled, rust-analyzer will emit special token types for punctuation tokens instead
+of the generic `punctuation` token type.
+--
 [[rust-analyzer.semanticHighlighting.strings.enable]]rust-analyzer.semanticHighlighting.strings.enable (default: `true`)::
 +
 --
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index c482fcbed0e..9bd3b6a692b 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -861,3 +861,14 @@ For example, if you want to run https://crates.io/crates/cargo-watch[`cargo watc
     "isBackground": true
 }
 ```
+
+==== Live Share
+
+VS Code Live Share has partial support for rust-analyzer.
+
+Live Share _requires_ the official Microsoft build of VS Code, OSS builds will not work correctly.
+
+The host's rust-analyzer instance will be shared with all guests joining the session.
+The guests do not have to have the rust-analyzer extension installed for this to work.
+
+If you are joining a Live Share session and _do_ have rust-analyzer installed locally, commands from the command palette will not work correctly since they will attempt to communicate with the local server.
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 67eabc313c8..767c5875bf7 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1084,6 +1084,36 @@
                     "default": false,
                     "type": "boolean"
                 },
+                "rust-analyzer.semanticHighlighting.doc.comment.inject.enable": {
+                    "markdownDescription": "Inject additional highlighting into doc comments.\n\nWhen enabled, rust-analyzer will highlight rust source in doc comments as well as intra\ndoc links.",
+                    "default": true,
+                    "type": "boolean"
+                },
+                "rust-analyzer.semanticHighlighting.operator.enable": {
+                    "markdownDescription": "Use semantic tokens for operators.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for operator tokens when\nthey are tagged with modifiers.",
+                    "default": true,
+                    "type": "boolean"
+                },
+                "rust-analyzer.semanticHighlighting.operator.specialization.enable": {
+                    "markdownDescription": "Use specialized semantic tokens for operators.\n\nWhen enabled, rust-analyzer will emit special token types for operator tokens instead\nof the generic `operator` token type.",
+                    "default": false,
+                    "type": "boolean"
+                },
+                "rust-analyzer.semanticHighlighting.punctuation.enable": {
+                    "markdownDescription": "Use semantic tokens for punctuations.\n\nWhen disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when\nthey are tagged with modifiers or have a special role.",
+                    "default": false,
+                    "type": "boolean"
+                },
+                "rust-analyzer.semanticHighlighting.punctuation.separate.macro.bang": {
+                    "markdownDescription": "When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro\ncalls.",
+                    "default": false,
+                    "type": "boolean"
+                },
+                "rust-analyzer.semanticHighlighting.punctuation.specialization.enable": {
+                    "markdownDescription": "Use specialized semantic tokens for punctuations.\n\nWhen enabled, rust-analyzer will emit special token types for punctuation tokens instead\nof the generic `punctuation` token type.",
+                    "default": false,
+                    "type": "boolean"
+                },
                 "rust-analyzer.semanticHighlighting.strings.enable": {
                     "markdownDescription": "Use semantic tokens for strings.\n\nIn some editors (e.g. vscode) semantic tokens override other highlighting grammars.\nBy disabling semantic tokens for strings, other grammars can be used to highlight\ntheir contents.",
                     "default": true,
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index 27ab31db8db..05d4d08f70b 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -5,7 +5,6 @@ import * as Is from "vscode-languageclient/lib/common/utils/is";
 import { assert } from "./util";
 import { WorkspaceEdit } from "vscode";
 import { Workspace } from "./ctx";
-import { updateConfig } from "./config";
 import { substituteVariablesInEnv } from "./config";
 import { outputChannel, traceOutputChannel } from "./main";
 import { randomUUID } from "crypto";
@@ -86,11 +85,6 @@ export async function createClient(
 
     let initializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
 
-    // Update outdated user configs
-    await updateConfig(initializationOptions).catch((err) => {
-        void vscode.window.showErrorMessage(`Failed updating old config keys: ${err.message}`);
-    });
-
     if (workspace.kind === "Detached Files") {
         initializationOptions = {
             detachedFiles: workspace.files.map((file) => file.uri.fsPath),
@@ -105,22 +99,6 @@ export async function createClient(
         traceOutputChannel: traceOutputChannel(),
         outputChannel: outputChannel(),
         middleware: {
-            async handleDiagnostics(uri, diagnostics, next) {
-                // Workaround for https://github.com/microsoft/vscode/issues/155531
-                for (const diagnostic of diagnostics) {
-                    if (!diagnostic.message) {
-                        diagnostic.message = " ";
-                    }
-                    if (diagnostic.relatedInformation) {
-                        for (const relatedInformation of diagnostic.relatedInformation) {
-                            if (!relatedInformation.message) {
-                                relatedInformation.message = " ";
-                            }
-                        }
-                    }
-                }
-                next(uri, diagnostics);
-            },
             async provideHover(
                 document: vscode.TextDocument,
                 position: vscode.Position,
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index b83582a344a..a9c0f079b3d 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -3,8 +3,6 @@ import * as vscode from "vscode";
 import { Env } from "./client";
 import { log } from "./util";
 
-export type UpdatesChannel = "stable" | "nightly";
-
 export type RunnableEnvCfg =
     | undefined
     | Record<string, string>
@@ -175,100 +173,6 @@ export class Config {
     }
 }
 
-export async function updateConfig(config: vscode.WorkspaceConfiguration) {
-    const renames = [
-        ["assist.allowMergingIntoGlobImports", "imports.merge.glob"],
-        ["assist.exprFillDefault", "assist.expressionFillDefault"],
-        ["assist.importEnforceGranularity", "imports.granularity.enforce"],
-        ["assist.importGranularity", "imports.granularity.group"],
-        ["assist.importMergeBehavior", "imports.granularity.group"],
-        ["assist.importMergeBehaviour", "imports.granularity.group"],
-        ["assist.importGroup", "imports.group.enable"],
-        ["assist.importPrefix", "imports.prefix"],
-        ["primeCaches.enable", "cachePriming.enable"],
-        ["cache.warmup", "cachePriming.enable"],
-        ["cargo.loadOutDirsFromCheck", "cargo.buildScripts.enable"],
-        ["cargo.runBuildScripts", "cargo.buildScripts.enable"],
-        ["cargo.runBuildScriptsCommand", "cargo.buildScripts.overrideCommand"],
-        ["cargo.useRustcWrapperForBuildScripts", "cargo.buildScripts.useRustcWrapper"],
-        ["completion.snippets", "completion.snippets.custom"],
-        ["diagnostics.enableExperimental", "diagnostics.experimental.enable"],
-        ["experimental.procAttrMacros", "procMacro.attributes.enable"],
-        ["highlighting.strings", "semanticHighlighting.strings.enable"],
-        ["highlightRelated.breakPoints", "highlightRelated.breakPoints.enable"],
-        ["highlightRelated.exitPoints", "highlightRelated.exitPoints.enable"],
-        ["highlightRelated.yieldPoints", "highlightRelated.yieldPoints.enable"],
-        ["highlightRelated.references", "highlightRelated.references.enable"],
-        ["hover.documentation", "hover.documentation.enable"],
-        ["hover.linksInHover", "hover.links.enable"],
-        ["hoverActions.linksInHover", "hover.links.enable"],
-        ["hoverActions.debug", "hover.actions.debug.enable"],
-        ["hoverActions.enable", "hover.actions.enable.enable"],
-        ["hoverActions.gotoTypeDef", "hover.actions.gotoTypeDef.enable"],
-        ["hoverActions.implementations", "hover.actions.implementations.enable"],
-        ["hoverActions.references", "hover.actions.references.enable"],
-        ["hoverActions.run", "hover.actions.run.enable"],
-        ["inlayHints.chainingHints", "inlayHints.chainingHints.enable"],
-        ["inlayHints.closureReturnTypeHints", "inlayHints.closureReturnTypeHints.enable"],
-        ["inlayHints.hideNamedConstructorHints", "inlayHints.typeHints.hideNamedConstructor"],
-        ["inlayHints.parameterHints", "inlayHints.parameterHints.enable"],
-        ["inlayHints.reborrowHints", "inlayHints.reborrowHints.enable"],
-        ["inlayHints.typeHints", "inlayHints.typeHints.enable"],
-        ["lruCapacity", "lru.capacity"],
-        ["runnables.cargoExtraArgs", "runnables.extraArgs"],
-        ["runnables.overrideCargo", "runnables.command"],
-        ["rustcSource", "rustc.source"],
-        ["rustfmt.enableRangeFormatting", "rustfmt.rangeFormatting.enable"],
-    ];
-
-    for (const [oldKey, newKey] of renames) {
-        const inspect = config.inspect(oldKey);
-        if (inspect !== undefined) {
-            const valMatrix = [
-                {
-                    val: inspect.globalValue,
-                    langVal: inspect.globalLanguageValue,
-                    target: vscode.ConfigurationTarget.Global,
-                },
-                {
-                    val: inspect.workspaceFolderValue,
-                    langVal: inspect.workspaceFolderLanguageValue,
-                    target: vscode.ConfigurationTarget.WorkspaceFolder,
-                },
-                {
-                    val: inspect.workspaceValue,
-                    langVal: inspect.workspaceLanguageValue,
-                    target: vscode.ConfigurationTarget.Workspace,
-                },
-            ];
-            for (const { val, langVal, target } of valMatrix) {
-                const patch = (val: unknown) => {
-                    // some of the updates we do only append "enable" or "custom"
-                    // that means on the next run we would find these again, but as objects with
-                    // these properties causing us to destroy the config
-                    // so filter those already updated ones out
-                    return (
-                        val !== undefined &&
-                        !(
-                            typeof val === "object" &&
-                            val !== null &&
-                            (oldKey === "completion.snippets" || !val.hasOwnProperty("custom"))
-                        )
-                    );
-                };
-                if (patch(val)) {
-                    await config.update(newKey, val, target, false);
-                    await config.update(oldKey, undefined, target, false);
-                }
-                if (patch(langVal)) {
-                    await config.update(newKey, langVal, target, true);
-                    await config.update(oldKey, undefined, target, true);
-                }
-            }
-        }
-    }
-}
-
 export function substituteVariablesInEnv(env: Env): Env {
     const missingDeps = new Set<string>();
     // vscode uses `env:ENV_NAME` for env vars resolution, and it's easier
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index a9847dd2a65..e9b62e0cc25 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -33,7 +33,7 @@ export function outputChannel() {
 }
 
 export interface RustAnalyzerExtensionApi {
-    client: lc.LanguageClient;
+    client?: lc.LanguageClient;
 }
 
 export async function activate(
@@ -48,6 +48,23 @@ export async function activate(
 }
 
 async function tryActivate(context: vscode.ExtensionContext): Promise<RustAnalyzerExtensionApi> {
+    // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
+    // only those are in use.
+    // (r-a still somewhat works with Live Share, because commands are tunneled to the host)
+    const folders = (vscode.workspace.workspaceFolders || []).filter(
+        (folder) => folder.uri.scheme === "file"
+    );
+    const rustDocuments = vscode.workspace.textDocuments.filter((document) =>
+        isRustDocument(document)
+    );
+
+    if (folders.length === 0 && rustDocuments.length === 0) {
+        // FIXME: Ideally we would choose not to activate at all (and avoid registering
+        // non-functional editor commands), but VS Code doesn't seem to have a good way of doing
+        // that
+        return {};
+    }
+
     const config = new Config(context);
     const state = new PersistentState(context.globalState);
     const serverPath = await bootstrap(context, config, state).catch((err) => {
@@ -60,18 +77,11 @@ async function tryActivate(context: vscode.ExtensionContext): Promise<RustAnalyz
         throw new Error(message);
     });
 
-    if ((vscode.workspace.workspaceFolders || []).length === 0) {
-        const rustDocuments = vscode.workspace.textDocuments.filter((document) =>
-            isRustDocument(document)
-        );
-        if (rustDocuments.length > 0) {
-            ctx = await Ctx.create(config, context, serverPath, {
-                kind: "Detached Files",
-                files: rustDocuments,
-            });
-        } else {
-            throw new Error("no rust files are opened");
-        }
+    if (folders.length === 0) {
+        ctx = await Ctx.create(config, context, serverPath, {
+            kind: "Detached Files",
+            files: rustDocuments,
+        });
     } else {
         // Note: we try to start the server before we activate type hints so that it
         // registers its `onDidChangeDocument` handler before us.
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
index 4a59c4c0fad..36d728456f7 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
@@ -15,7 +15,7 @@ pub(crate) fn socket_transport(
     stream: TcpStream,
 ) -> (Sender<Message>, Receiver<Message>, IoThreads) {
     let (reader_receiver, reader) = make_reader(stream.try_clone().unwrap());
-    let (writer_sender, writer) = make_write(stream.try_clone().unwrap());
+    let (writer_sender, writer) = make_write(stream);
     let io_threads = make_io_threads(reader, writer);
     (writer_sender, reader_receiver, io_threads)
 }